From 73547da0003741ff6d574d2556557c157a90238f Mon Sep 17 00:00:00 2001 From: Sanad Liaquat Date: Thu, 14 Feb 2019 04:35:21 +0000 Subject: [PATCH 1/6] Merge branch 'qa-ml-quarantine-context' into 'master' [QA] Skip contexts in quarantine See merge request gitlab-org/gitlab-ce!24942 (cherry picked from commit c6016ac8a8c12a736617e5250b63e0c930dda207) a2229074 Skip contexts in quarantine a3f93880 Refactor rspec config quarantine before blocks --- qa/spec/spec_helper.rb | 67 +++++--- qa/spec/spec_helper_spec.rb | 332 ++++++++++++++++++++---------------- 2 files changed, 226 insertions(+), 173 deletions(-) diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index 0f3cf5f4408..cddaa6fc6e0 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -17,26 +17,16 @@ RSpec.configure do |config| end end - config.before do |example| - QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug? - - # If quarantine is tagged, skip tests that have other metadata unless - # they're also tagged. This lets us run quarantined tests in a particular - # category without running tests in other categories. - # E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged - # 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests - # using `--tag quarantine --tag smoke`, without this check we'd end up - # running that ldap test as well. - if config.inclusion_filter[:quarantine] - skip("Running tests tagged with all of #{config.inclusion_filter.rules.keys}") unless quarantine_and_optional_other_tag?(example, config) + config.before(:context) do + if self.class.metadata.keys.include?(:quarantine) + skip_or_run_quarantined_tests(self.class.metadata.keys, config.inclusion_filter.rules.keys) end end - config.before(:each, :quarantine) do |example| - # Skip tests in quarantine unless we explicitly focus on them - # We could use an exclusion filter, but this way the test report will list - # the quarantined tests when they're not run so that we're aware of them - skip('In quarantine') unless config.inclusion_filter[:quarantine] + config.before do |example| + QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug? + + skip_or_run_quarantined_tests(example.metadata.keys, config.inclusion_filter.rules.keys) end config.expect_with :rspec do |expectations| @@ -55,18 +45,41 @@ RSpec.configure do |config| Kernel.srand config.seed end +# Skip tests in quarantine unless we explicitly focus on them. +# Skip the entire context if a context is tagged. This avoids running before +# blocks unnecessarily. +# If quarantine is focussed, skip tests/contexts that have other metadata +# unless they're also focussed. This lets us run quarantined tests in a +# particular category without running tests in other categories. +# E.g., if a test is tagged 'smoke' and 'quarantine', and another is tagged +# 'ldap' and 'quarantine', if we wanted to run just quarantined smoke tests +# using `--tag quarantine --tag smoke`, without this check we'd end up +# running that ldap test as well. +# We could use an exclusion filter, but this way the test report will list +# the quarantined tests when they're not run so that we're aware of them +def skip_or_run_quarantined_tests(metadata_keys, filter_keys) + included_filters = filters_other_than_quarantine(filter_keys) + + if filter_keys.include?(:quarantine) + skip("Only running tests tagged with :quarantine and any of #{included_filters}") unless quarantine_and_optional_other_tag?(metadata_keys, included_filters) + else + skip('In quarantine') if metadata_keys.include?(:quarantine) + end +end + +def filters_other_than_quarantine(filter_keys) + filter_keys.reject { |key| key == :quarantine } +end + # Checks if a test has the 'quarantine' tag and other tags in the inclusion filter. # # Returns true if -# - the example metadata includes the quarantine tag -# - and the metadata and inclusion filter both have any other tag -# - or no other tags are in the inclusion filter -def quarantine_and_optional_other_tag?(example, config) - return false unless example.metadata.keys.include? :quarantine - - filters_other_than_quarantine = config.inclusion_filter.rules.keys.reject { |key| key == :quarantine } - - return true if filters_other_than_quarantine.empty? +# - the metadata includes the quarantine tag +# - and the metadata and inclusion filter both have any other tag +# - or no other tags are in the inclusion filter +def quarantine_and_optional_other_tag?(metadata_keys, included_filters) + return false unless metadata_keys.include? :quarantine + return true if included_filters.empty? - filters_other_than_quarantine.any? { |key| example.metadata.keys.include? key } + included_filters.any? { |key| metadata_keys.include? key } end diff --git a/qa/spec/spec_helper_spec.rb b/qa/spec/spec_helper_spec.rb index f001200fb52..2427999e110 100644 --- a/qa/spec/spec_helper_spec.rb +++ b/qa/spec/spec_helper_spec.rb @@ -10,79 +10,79 @@ describe 'rspec config tests' do end end + context 'default' do + it_behaves_like 'passing tests' + end + context 'foo', :foo do it_behaves_like 'passing tests' end - context 'default' do + context 'quarantine', :quarantine do + it_behaves_like 'passing tests' + end + + context 'bar quarantine', :bar, :quarantine do it_behaves_like 'passing tests' end end end - context 'default config' do - it 'tests are skipped if in quarantine' do + context 'with no tags focussed' do + before do group.run + end - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) - - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + context 'in a context tagged :foo' do + it 'skips tests in quarantine' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to eq(2) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end + end - ex = default_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + context 'in an untagged context' do + it 'skips tests in quarantine' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') - end - end + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - context "with 'quarantine' tagged" do - before do - RSpec.configure do |config| - config.inclusion_filter = :quarantine - end - end - after do - RSpec.configure do |config| - config.inclusion_filter.clear + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') end end - it "only quarantined tests are run" do - group.run - - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to be(1) - - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(2) - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to be(1) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end end end - context "with 'foo' tagged" do + context 'with :quarantine focussed' do before do RSpec.configure do |config| - config.inclusion_filter = :foo + config.inclusion_filter = :quarantine end group.run @@ -93,30 +93,50 @@ describe 'rspec config tests' do end end - it "tests are not run if not tagged 'foo'" do - default_context = group.children.find { |c| c.description == "default" } - expect(default_context.descendant_filtered_examples.count).to eq(0) + context 'in an untagged context' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(1) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end end - it "tests are skipped if in quarantine" do - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(1) - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end + end + + context 'in a context tagged :quarantine' do + it 'runs all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end end end - context "with 'quarantine' and 'foo' tagged" do + context 'with a non-quarantine tag (:foo) focussed' do before do RSpec.configure do |config| - config.inclusion_filter = { quarantine: true, foo: true } + config.inclusion_filter = :foo end + + group.run end after do RSpec.configure do |config| @@ -124,38 +144,43 @@ describe 'rspec config tests' do end end - it 'of tests tagged foo, only tests in quarantine run' do - group.run + context 'in an untagged context' do + it 'runs no tests' do + context = group.children.find { |c| c.description == "default" } + expect(context.descendant_filtered_examples.count).to eq(0) + end + end - foo_context = group.children.find { |c| c.description == "foo" } - foo_examples = foo_context.descendant_filtered_examples - expect(foo_examples.count).to eq(2) + context 'in a context tagged :foo' do + it 'skips quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = foo_examples.find { |e| e.description == "not in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:quarantine, :foo]') + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - ex = foo_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('In quarantine') + end end - it 'if tests are not tagged they are skipped, even if they are in quarantine' do - group.run - default_context = group.children.find { |c| c.description == "default" } - default_examples = default_context.descendant_filtered_examples - expect(default_examples.count).to eq(1) - - ex = default_examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:quarantine, :foo]') + context 'in a context tagged :quarantine' do + it 'runs no tests' do + context = group.children.find { |c| c.description == "quarantine" } + expect(context.descendant_filtered_examples.count).to eq(0) + end end end - context "with 'foo' and 'bar' tagged" do + context 'with :quarantine and a non-quarantine tag (:foo) focussed' do before do RSpec.configure do |config| - config.inclusion_filter = { bar: true, foo: true } + config.inclusion_filter = { quarantine: true, foo: true } end + + group.run end after do RSpec.configure do |config| @@ -163,67 +188,67 @@ describe 'rspec config tests' do end end - it "runs tests tagged either 'foo' or 'bar'" do - group = RSpec.describe do - example 'foo', :foo do - end - example 'bar', :bar do - end - example 'foo and bar', :foo, :bar do - end - end - - group.run - expect(group.examples.count).to eq(3) + context 'in an untagged context' do + it 'ignores untagged tests and skips tests even if in quarantine' do + context = group.children.find { |c| c.description == "default" } + examples = context.descendant_filtered_examples + expect(examples.count).to eq(1) - ex = group.examples.find { |e| e.description == "foo" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end + end - ex = group.examples.find { |e| e.description == "bar" } - expect(ex.execution_result.status).to eq(:passed) + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "foo and bar" } - expect(ex.execution_result.status).to eq(:passed) - end + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) - it "skips quarantined tests tagged 'foo' and/or 'bar'" do - group = RSpec.describe do - example 'foo in quarantine', :foo, :quarantine do - end - example 'foo and bar in quarantine', :foo, :bar, :quarantine do - end + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) end + end - group.run - expect(group.examples.count).to eq(2) + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "foo in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) - ex = group.examples.find { |e| e.description == "foo and bar in quarantine" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('In quarantine') + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end end - it "ignores quarantined tests not tagged either 'foo' or 'bar'" do - group = RSpec.describe do - example 'in quarantine', :quarantine do - end - end + context 'in a context tagged :bar and :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - group.run + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) - ex = group.examples.find { |e| e.description == "in quarantine" } - expect(ex.execution_result.status).to be_nil + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + end end end - context "with 'foo' and 'bar' and 'quarantined' tagged" do + context 'with :quarantine and multiple non-quarantine tags focussed' do before do RSpec.configure do |config| config.inclusion_filter = { bar: true, foo: true, quarantine: true } end + + group.run end after do RSpec.configure do |config| @@ -231,34 +256,49 @@ describe 'rspec config tests' do end end - it "runs tests tagged 'quarantine' and 'foo' or 'bar'" do - group = RSpec.describe do - example 'foo', :foo do - end - example 'bar and quarantine', :bar, :quarantine do - end - example 'foo and bar', :foo, :bar do - end - example 'foo, bar, and quarantine', :foo, :bar, :quarantine do - end + context 'in a context tagged :foo' do + it 'only runs quarantined tests' do + context = group.children.find { |c| c.description == "foo" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) + + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') end + end - group.run - expect(group.examples.count).to eq(4) + context 'in a context tagged :quarantine' do + it 'skips all tests' do + context = group.children.find { |c| c.description == "quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "foo" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:bar, :foo, :quarantine]') + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') - ex = group.examples.find { |e| e.description == "bar and quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:pending) + expect(ex.execution_result.pending_message).to eq('Only running tests tagged with :quarantine and any of [:bar, :foo]') + end + end - ex = group.examples.find { |e| e.description == "foo and bar" } - expect(ex.execution_result.status).to eq(:pending) - expect(ex.execution_result.pending_message).to eq('Running tests tagged with all of [:bar, :foo, :quarantine]') + context 'in a context tagged :bar and :quarantine' do + it 'runs all tests' do + context = group.children.find { |c| c.description == "bar quarantine" } + examples = context.descendant_filtered_examples + expect(examples.count).to be(2) - ex = group.examples.find { |e| e.description == "foo, bar, and quarantine" } - expect(ex.execution_result.status).to eq(:passed) + ex = examples.find { |e| e.description == "in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + + ex = examples.find { |e| e.description == "not in quarantine" } + expect(ex.execution_result.status).to eq(:passed) + end end end end -- GitLab From 31e5dc77290cd507088223a5017157cd1e973e7b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 14 Feb 2019 16:01:47 +0000 Subject: [PATCH 2/6] Merge branch 'syntax-highlighting-again' into 'master' Fix suggested changes syntax highlighting See merge request gitlab-org/gitlab-ce!25116 (cherry picked from commit d4b973fd515f70ead359510e553173bb2be8a802) adddcbd3 Fix suggested changes syntax highlighting 6d3626ef Add fix for suggested changes syntax highlighting b12a8b35 Move note-related classes into note_body 3f3eff4b Fix eslint issue 22839d1c Move class to before @apply --- app/assets/javascripts/notes/components/note_body.vue | 1 + .../vue_shared/components/markdown/suggestions.vue | 2 +- app/assets/stylesheets/framework/mixins.scss | 4 ---- changelogs/unreleased/syntax-highlighting-again.yml | 5 +++++ 4 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/syntax-highlighting-again.yml diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index ff303d0f55a..fb1d98355b3 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -95,6 +95,7 @@ export default {
-
+
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index 9837b1a6bd0..b9d0c0d4d96 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -36,10 +36,6 @@ width: fit-content; } - tbody { - background-color: $white-light; - } - tr { th { border-bottom: solid 2px $gl-gray-100; diff --git a/changelogs/unreleased/syntax-highlighting-again.yml b/changelogs/unreleased/syntax-highlighting-again.yml new file mode 100644 index 00000000000..14223fc0927 --- /dev/null +++ b/changelogs/unreleased/syntax-highlighting-again.yml @@ -0,0 +1,5 @@ +--- +title: Fix suggested changes syntax highlighting +merge_request: 25116 +author: +type: fixed -- GitLab From 38ef0bbe7ee976f00896d9cdc56aa74618b6a167 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 14 Feb 2019 08:41:38 +0000 Subject: [PATCH 3/6] Merge branch 'regression-commits-header-link' into 'master' Fixed link alignment See merge request gitlab-org/gitlab-ce!25162 (cherry picked from commit e865ee2b57ddcde51920a7b84189862dd4011b7e) 9189f14f Fixed link alignment bf1a7910 Fixed static analysis issue c0db4c7e Replaced class on caret b96f9011 Replaced flex with vertical-align-middle 665c1b96 Added mr-2 class back 91b97ae6 Fixed visual issue when MR has conflicts --- .../components/states/commits_header.vue | 4 ++-- app/assets/stylesheets/pages/merge_requests.scss | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue index a1d3a09cca4..33963d5e1e6 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue @@ -73,14 +73,14 @@ export default { {{ __('Collapse') }} - + {{ modifyLinkMessage }} diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 135730d71e9..a27594a5080 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -1019,3 +1019,8 @@ z-index: 99999; background: $black-transparent; } + +.source-branch-removal-status { + padding-left: 50px; + padding-bottom: $gl-padding; +} -- GitLab From 33799a15368e8fab888a2479ccf5de96b8c91490 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Wed, 13 Feb 2019 17:28:12 +0000 Subject: [PATCH 4/6] Merge branch '57160-merge-request-tabs-header-is-missing-bottom-border' into 'master' Resolve "Merge Request Tabs Header is missing bottom border" Closes #57160 See merge request gitlab-org/gitlab-ce!25198 (cherry picked from commit 20226ed8e4231e4213db5644dab0fa576efbb8bc) 04853a4a Return border bottom on MR Tabs --- app/assets/stylesheets/pages/merge_requests.scss | 8 +++----- ...merge-request-tabs-header-is-missing-bottom-border.yml | 5 +++++ 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/57160-merge-request-tabs-header-is-missing-bottom-border.yml diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index a27594a5080..790d438c7e2 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -738,6 +738,8 @@ z-index: 103; background: $gray-light; color: $gl-text-color; + margin-top: -1px; + border-top: 1px solid $border-color; .mr-version-menus-container { display: flex; @@ -789,7 +791,6 @@ position: sticky; top: $header-height + $mr-tabs-height; width: 100%; - border-top: 1px solid $border-color; &.is-fileTreeOpen { margin-left: -16px; @@ -810,10 +811,7 @@ top: $header-height; z-index: 200; background-color: $white-light; - - @include media-breakpoint-down(md) { - border-bottom: 1px solid $border-color; - } + border-bottom: 1px solid $border-color; @include media-breakpoint-up(sm) { position: sticky; diff --git a/changelogs/unreleased/57160-merge-request-tabs-header-is-missing-bottom-border.yml b/changelogs/unreleased/57160-merge-request-tabs-header-is-missing-bottom-border.yml new file mode 100644 index 00000000000..3146d07db3d --- /dev/null +++ b/changelogs/unreleased/57160-merge-request-tabs-header-is-missing-bottom-border.yml @@ -0,0 +1,5 @@ +--- +title: Return bottom border on MR Tabs +merge_request: !25198 +author: +type: fixed -- GitLab From 72defb15ba8392af22040f2b918643f6d108305d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 13 Feb 2019 21:37:12 +0000 Subject: [PATCH 5/6] Merge branch '57634-issue-when-viewing-a-document-with-footnotes-actionview-template-error-undefined-method-at_css-for-nil-nilclass' into 'master' Issue when viewing a document with footnotes Closes #57634 See merge request gitlab-org/gitlab-ce!25199 (cherry picked from commit 69c19b392e4636093050f576d3056a10371b01b2) f8241f25 Properly handle multiple refs to same footnote --- lib/banzai/filter/footnote_filter.rb | 23 +++++++++++++------ .../lib/banzai/filter/footnote_filter_spec.rb | 2 ++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/banzai/filter/footnote_filter.rb b/lib/banzai/filter/footnote_filter.rb index 97527976437..de133774dfa 100644 --- a/lib/banzai/filter/footnote_filter.rb +++ b/lib/banzai/filter/footnote_filter.rb @@ -29,21 +29,30 @@ module Banzai # Sanitization stripped off the section wrapper - add it back in first_footnote.parent.wrap('
') rand_suffix = "-#{random_number}" + modified_footnotes = {} doc.css('sup > a[id]').each do |link_node| ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX) footnote_node = doc.at_css("li[id=#{fn_id(ref_num)}]") - backref_node = footnote_node.at_css("a[href=\"##{fnref_id(ref_num)}\"]") - if ref_num =~ INTEGER_PATTERN && footnote_node && backref_node - link_node[:href] += rand_suffix - link_node[:id] += rand_suffix - footnote_node[:id] += rand_suffix - backref_node[:href] += rand_suffix + if INTEGER_PATTERN.match?(ref_num) && (footnote_node || modified_footnotes[ref_num]) + link_node[:href] += rand_suffix + link_node[:id] += rand_suffix # Sanitization stripped off class - add it back in link_node.parent.append_class('footnote-ref') - backref_node.append_class('footnote-backref') + + unless modified_footnotes[ref_num] + footnote_node[:id] += rand_suffix + backref_node = footnote_node.at_css("a[href=\"##{fnref_id(ref_num)}\"]") + + if backref_node + backref_node[:href] += rand_suffix + backref_node.append_class('footnote-backref') + end + + modified_footnotes[ref_num] = true + end end end diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb index 2e50e4e2351..c6dcb4e46fd 100644 --- a/spec/lib/banzai/filter/footnote_filter_spec.rb +++ b/spec/lib/banzai/filter/footnote_filter_spec.rb @@ -11,6 +11,7 @@ describe Banzai::Filter::FootnoteFilter do let(:footnote) do <<~EOF

first1 and second2

+

same reference1

  1. one

    @@ -25,6 +26,7 @@ describe Banzai::Filter::FootnoteFilter do let(:filtered_footnote) do <<~EOF

    first1 and second2

    +

    same reference1

    1. one

      -- GitLab From 17380cf90ce6f12ae06384d2d7a1d04bd928e6a5 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 13 Feb 2019 19:56:32 +0000 Subject: [PATCH 6/6] Merge branch 'sh-fix-content-disposition-inline' into 'master' Fix Content-Disposition hard-coded to attachments Closes #57660 See merge request gitlab-org/gitlab-ce!25214 (cherry picked from commit a77a1e1b4faaa1240e831b5da7903cd1d52e75a3) 134420f2 Fix Content-Disposition hard-coded to attachments --- app/controllers/concerns/send_file_upload.rb | 2 +- .../concerns/send_file_upload_spec.rb | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb index 9ca54c5519b..28e4cece548 100644 --- a/app/controllers/concerns/send_file_upload.rb +++ b/app/controllers/concerns/send_file_upload.rb @@ -3,7 +3,7 @@ module SendFileUpload def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment') if attachment - response_disposition = ::Gitlab::ContentDisposition.format(disposition: 'attachment', filename: attachment) + response_disposition = ::Gitlab::ContentDisposition.format(disposition: disposition, filename: attachment) # Response-Content-Type will not override an existing Content-Type in # Google Cloud Storage, so the metadata needs to be cleared on GCS for diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb index a07113a6156..cf3b24f50a3 100644 --- a/spec/controllers/concerns/send_file_upload_spec.rb +++ b/spec/controllers/concerns/send_file_upload_spec.rb @@ -52,6 +52,23 @@ describe SendFileUpload do end end + context 'with inline image' do + let(:filename) { 'test.png' } + let(:params) { { disposition: 'inline', attachment: filename } } + + it 'sends a file with inline disposition' do + # Notice the filename= is omitted from the disposition; this is because + # Rails 5 will append this header in send_file + expected_params = { + filename: 'test.png', + disposition: "inline; filename*=UTF-8''test.png" + } + expect(controller).to receive(:send_file).with(uploader.path, expected_params) + + subject + end + end + context 'with attachment' do let(:filename) { 'test.js' } let(:params) { { attachment: filename } } -- GitLab