From b93af54ce23667379bd151f614e5988523a40c68 Mon Sep 17 00:00:00 2001 From: Jose Vargas Date: Wed, 30 Jan 2019 13:40:22 -0600 Subject: [PATCH 1/8] Fix error tracking page, not showing an empty state This MR adds a missing empty state for when a backend response contains an empty error list, it shows the table but with `no data to display` empty state, also adds a reload button that allows to refresh for data --- .../components/error_tracking_list.vue | 26 ++++++++++++------- .../error_tracking/store/actions.js | 15 ++++++++++- ...56851-error-tracking-page-seems-broken.yml | 5 ++++ locale/gitlab.pot | 8 +++++- .../components/error_tracking_list_spec.js | 22 ++++++++++++++-- 5 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 changelogs/unreleased/56851-error-tracking-page-seems-broken.yml diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index 6981afe1ead..43ae54133af 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -48,7 +48,7 @@ export default { } }, methods: { - ...mapActions(['startPolling']), + ...mapActions(['startPolling', 'restartPolling']), }, }; @@ -56,19 +56,17 @@ export default { + diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js index 11aec312368..d42e4f145dc 100644 --- a/app/assets/javascripts/error_tracking/store/actions.js +++ b/app/assets/javascripts/error_tracking/store/actions.js @@ -6,7 +6,7 @@ import { __, sprintf } from '~/locale'; let eTagPoll; -export function startPolling({ commit }, endpoint) { +export function startPolling({ commit, dispatch }, endpoint) { eTagPoll = new Poll({ resource: Service, method: 'getErrorList', @@ -18,6 +18,7 @@ export function startPolling({ commit }, endpoint) { commit(types.SET_ERRORS, data.errors); commit(types.SET_EXTERNAL_URL, data.external_url); commit(types.SET_LOADING, false); + dispatch('stopPolling'); }, errorCallback: response => { let errorMessage = ''; @@ -36,4 +37,16 @@ export function startPolling({ commit }, endpoint) { eTagPoll.makeRequest(); } +export const stopPolling = () => { + if (eTagPoll) eTagPoll.stop(); +}; + +export function restartPolling({ commit }) { + commit(types.SET_ERRORS, []); + commit(types.SET_EXTERNAL_URL, ''); + commit(types.SET_LOADING, true); + + if (eTagPoll) eTagPoll.restart(); +} + export default () => {}; diff --git a/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml b/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml new file mode 100644 index 00000000000..ff4aebb9381 --- /dev/null +++ b/changelogs/unreleased/56851-error-tracking-page-seems-broken.yml @@ -0,0 +1,5 @@ +--- +title: Fix error tracking list page +merge_request: 24806 +author: +type: fixed diff --git a/locale/gitlab.pot b/locale/gitlab.pot index cb599e4744c..2955f87e69d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1386,6 +1386,9 @@ msgstr "" msgid "Chat" msgstr "" +msgid "Check again" +msgstr "" + msgid "Check the %{docs_link_start}documentation%{docs_link_end}." msgstr "" @@ -5000,7 +5003,7 @@ msgstr "" msgid "No due date" msgstr "" -msgid "No errors to display" +msgid "No errors to display." msgstr "" msgid "No estimate or time spent" @@ -8321,6 +8324,9 @@ msgstr "" msgid "View group labels" msgstr "" +msgid "View in Sentry" +msgstr "" + msgid "View it on GitLab" msgstr "" diff --git a/spec/javascripts/error_tracking/components/error_tracking_list_spec.js b/spec/javascripts/error_tracking/components/error_tracking_list_spec.js index 08bbb390993..503af3920a8 100644 --- a/spec/javascripts/error_tracking/components/error_tracking_list_spec.js +++ b/spec/javascripts/error_tracking/components/error_tracking_list_spec.js @@ -1,7 +1,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils'; import Vuex from 'vuex'; import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue'; -import { GlButton, GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui'; +import { GlButton, GlEmptyState, GlLoadingIcon, GlTable, GlLink } from '@gitlab/ui'; const localVue = createLocalVue(); localVue.use(Vuex); @@ -9,6 +9,7 @@ localVue.use(Vuex); describe('ErrorTrackingList', () => { let store; let wrapper; + let actions; function mountComponent({ errorTrackingEnabled = true } = {}) { wrapper = shallowMount(ErrorTrackingList, { @@ -20,12 +21,17 @@ describe('ErrorTrackingList', () => { errorTrackingEnabled, illustrationPath: 'illustration/path', }, + stubs: { + 'gl-link': GlLink, + }, }); } beforeEach(() => { - const actions = { + actions = { getErrorList: () => {}, + startPolling: () => {}, + restartPolling: jasmine.createSpy('restartPolling'), }; const state = { @@ -83,6 +89,18 @@ describe('ErrorTrackingList', () => { expect(wrapper.find(GlTable).exists()).toBeTruthy(); expect(wrapper.find(GlButton).exists()).toBeTruthy(); }); + + it('shows a message prompting to refresh', () => { + const refreshLink = wrapper.vm.$refs.empty.querySelector('a'); + + expect(refreshLink.textContent.trim()).toContain('Check again'); + }); + + it('restarts polling', () => { + wrapper.find('.js-try-again').trigger('click'); + + expect(actions.restartPolling).toHaveBeenCalled(); + }); }); describe('error tracking feature disabled', () => { -- GitLab From be99adb1498420be74d05d3e328632b24b5725a6 Mon Sep 17 00:00:00 2001 From: Thong Kuah Date: Fri, 14 Dec 2018 10:38:03 +1300 Subject: [PATCH 2/8] Show pg_stat_activity before each test run Maybe this will help us debug https://gitlab.com/gitlab-org/gitlab-ee/issues/10154 --- spec/support/pg_stat_activity.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 spec/support/pg_stat_activity.rb diff --git a/spec/support/pg_stat_activity.rb b/spec/support/pg_stat_activity.rb new file mode 100644 index 00000000000..f93fba08a19 --- /dev/null +++ b/spec/support/pg_stat_activity.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +RSpec.configure do |config| + config.before do + if Gitlab::Database.postgresql? && ENV['PG_STAT_WARNING_THRESHOLD'] + warning_threshold = ENV['PG_STAT_WARNING_THRESHOLD'].to_i + results = ActiveRecord::Base.connection.execute('SELECT * FROM pg_stat_activity') + ntuples = results.ntuples + + warn("pg_stat_activity count: #{ntuples}") + + if ntuples > warning_threshold + results.each do |result| + warn result.inspect + end + end + end + end +end -- GitLab From f786dcb255ae3e2eb3618b09a474b90a34d6f743 Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Tue, 5 Mar 2019 04:22:33 +0000 Subject: [PATCH 3/8] Adding NFS warning to requirements --- doc/install/requirements.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index c1f2297f3be..8ab7189c2a6 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -51,6 +51,8 @@ Apart from a local hard drive you can also mount a volume that supports the netw If you have enough RAM memory and a recent CPU the speed of GitLab is mainly limited by hard drive seek times. Having a fast drive (7200 RPM and up) or a solid state drive (SSD) will improve the responsiveness of GitLab. +NOTE: **Note:** Since file system performance may affect GitLab's overall performance, we do not recommend using EFS for storage. See the [relevant documentation](../administration/high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details. + ### CPU - 1 core supports up to 100 users but the application can be a bit slower due to having all workers and background jobs running on the same core -- GitLab From b08f2407c19a0eb2c0cadbdf710ab6d56326d1d9 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Tue, 5 Mar 2019 10:07:16 +0100 Subject: [PATCH 4/8] Re-add babel plugins for dynamic imports With https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25597 we also removed the babel-plugin-dynamic-import-node. It is now throwing errors when we run jest with coverage. --- babel.config.js | 5 +++++ package.json | 1 + yarn.lock | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/babel.config.js b/babel.config.js index e3db4dcbc9a..78d14095b0b 100644 --- a/babel.config.js +++ b/babel.config.js @@ -41,6 +41,11 @@ if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') { // Jest is running in node environment if (BABEL_ENV === 'jest') { plugins.push('@babel/plugin-transform-modules-commonjs'); + /* + without the following, babel-plugin-istanbul throws an error: + https://gitlab.com/gitlab-org/gitlab-ce/issues/58390 + */ + plugins.push('babel-plugin-dynamic-import-node'); } module.exports = { presets, plugins }; diff --git a/package.json b/package.json index 251ab8789a5..45c95202531 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "@vue/test-utils": "^1.0.0-beta.25", "axios-mock-adapter": "^1.15.0", "babel-jest": "^24.1.0", + "babel-plugin-dynamic-import-node": "^2.2.0", "babel-plugin-istanbul": "^5.1.0", "babel-plugin-rewire": "^1.2.0", "chalk": "^2.4.1", diff --git a/yarn.lock b/yarn.lock index 332bb550e17..cb3ab9d9524 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1466,6 +1466,13 @@ babel-loader@^8.0.5: mkdirp "^0.5.1" util.promisify "^1.0.0" +babel-plugin-dynamic-import-node@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.2.0.tgz#c0adfb07d95f4a4495e9aaac6ec386c4d7c2524e" + integrity sha512-fP899ELUnTaBcIzmrW7nniyqqdYWrWuJUyPWHxFa/c7r7hS6KC8FscNfLlBNIoPSc55kYMGEEKjPjJGCLbE1qA== + dependencies: + object.assign "^4.1.0" + babel-plugin-istanbul@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.0.tgz#6892f529eff65a3e2d33d87dc5888ffa2ecd4a30" -- GitLab From 21779d00186d75349165d6c07dbe04aace68017c Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 24 Jan 2019 16:23:57 +0000 Subject: [PATCH 5/8] Add metadata about the GitLab server to GraphQL --- app/graphql/resolvers/metadata_resolver.rb | 11 +++++++ app/graphql/types/metadata_type.rb | 10 ++++++ app/graphql/types/query_type.rb | 10 +++++- app/policies/global_policy.rb | 4 +++ .../unreleased/56809-graphql-version-api.yml | 5 +++ lib/api/helpers/graphql_helpers.rb | 22 +++++++++++++ lib/api/version.rb | 18 ++++++++++- .../resolvers/metadata_resolver_spec.rb | 11 +++++++ spec/graphql/types/metadata_type_spec.rb | 5 +++ spec/graphql/types/query_type_spec.rb | 15 ++++++++- spec/policies/global_policy_spec.rb | 12 +++++++ .../api/graphql/metadata_query_spec.rb | 32 +++++++++++++++++++ spec/requests/api/version_spec.rb | 18 ++++++++++- spec/support/helpers/graphql_helpers.rb | 3 +- 14 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 app/graphql/resolvers/metadata_resolver.rb create mode 100644 app/graphql/types/metadata_type.rb create mode 100644 changelogs/unreleased/56809-graphql-version-api.yml create mode 100644 lib/api/helpers/graphql_helpers.rb create mode 100644 spec/graphql/resolvers/metadata_resolver_spec.rb create mode 100644 spec/graphql/types/metadata_type_spec.rb create mode 100644 spec/requests/api/graphql/metadata_query_spec.rb diff --git a/app/graphql/resolvers/metadata_resolver.rb b/app/graphql/resolvers/metadata_resolver.rb new file mode 100644 index 00000000000..3a79e6434fb --- /dev/null +++ b/app/graphql/resolvers/metadata_resolver.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Resolvers + class MetadataResolver < BaseResolver + type Types::MetadataType, null: false + + def resolve(**args) + { version: Gitlab::VERSION, revision: Gitlab.revision } + end + end +end diff --git a/app/graphql/types/metadata_type.rb b/app/graphql/types/metadata_type.rb new file mode 100644 index 00000000000..2d8bad0614b --- /dev/null +++ b/app/graphql/types/metadata_type.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Types + class MetadataType < ::Types::BaseObject + graphql_name 'Metadata' + + field :version, GraphQL::STRING_TYPE, null: false + field :revision, GraphQL::STRING_TYPE, null: false + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 954bcc0a5a3..472fe5d6ec2 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Types - class QueryType < BaseObject + class QueryType < ::Types::BaseObject graphql_name 'Query' field :project, Types::ProjectType, @@ -10,6 +10,14 @@ module Types description: "Find a project", authorize: :read_project + field :metadata, Types::MetadataType, + null: true, + resolver: Resolvers::MetadataResolver, + description: 'Metadata about GitLab' do |*args| + + authorize :read_instance_metadata + end + field :echo, GraphQL::STRING_TYPE, null: false, function: Functions::Echo.new end end diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb index 16c58730878..d412a591fdc 100644 --- a/app/policies/global_policy.rb +++ b/app/policies/global_policy.rb @@ -68,6 +68,10 @@ class GlobalPolicy < BasePolicy enable :read_users_list end + rule { ~anonymous }.policy do + enable :read_instance_metadata + end + rule { admin }.policy do enable :read_custom_attribute enable :update_custom_attribute diff --git a/changelogs/unreleased/56809-graphql-version-api.yml b/changelogs/unreleased/56809-graphql-version-api.yml new file mode 100644 index 00000000000..72a4b4e5819 --- /dev/null +++ b/changelogs/unreleased/56809-graphql-version-api.yml @@ -0,0 +1,5 @@ +--- +title: Add metadata about the GitLab server to GraphQL +merge_request: 24636 +author: +type: added diff --git a/lib/api/helpers/graphql_helpers.rb b/lib/api/helpers/graphql_helpers.rb new file mode 100644 index 00000000000..94010ab1bc2 --- /dev/null +++ b/lib/api/helpers/graphql_helpers.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module API + module Helpers + # GraphqlHelpers is used by the REST API when it is acting like a client + # against the graphql API. Helper code for the graphql server implementation + # should be in app/graphql/ or lib/gitlab/graphql/ + module GraphqlHelpers + def conditionally_graphql!(fallback:, query:, context: {}, transform: nil) + return fallback.call unless Feature.enabled?(:graphql) + + result = GitlabSchema.execute(query, context: context) + + if transform + transform.call(result) + else + result + end + end + end + end +end diff --git a/lib/api/version.rb b/lib/api/version.rb index 74cd857f447..eca1b529094 100644 --- a/lib/api/version.rb +++ b/lib/api/version.rb @@ -2,13 +2,29 @@ module API class Version < Grape::API + helpers ::API::Helpers::GraphqlHelpers + before { authenticate! } + METADATA_QUERY = <<~EOF + { + metadata { + version + revision + } + } + EOF + desc 'Get the version information of the GitLab instance.' do detail 'This feature was introduced in GitLab 8.13.' end get '/version' do - { version: Gitlab::VERSION, revision: Gitlab.revision } + conditionally_graphql!( + query: METADATA_QUERY, + context: { current_user: current_user }, + transform: ->(result) { result.dig('data', 'metadata') }, + fallback: -> { { version: Gitlab::VERSION, revision: Gitlab.revision } } + ) end end end diff --git a/spec/graphql/resolvers/metadata_resolver_spec.rb b/spec/graphql/resolvers/metadata_resolver_spec.rb new file mode 100644 index 00000000000..e662ed127a5 --- /dev/null +++ b/spec/graphql/resolvers/metadata_resolver_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Resolvers::MetadataResolver do + include GraphqlHelpers + + describe '#resolve' do + it 'returns version and revision' do + expect(resolve(described_class)).to eq(version: Gitlab::VERSION, revision: Gitlab.revision) + end + end +end diff --git a/spec/graphql/types/metadata_type_spec.rb b/spec/graphql/types/metadata_type_spec.rb new file mode 100644 index 00000000000..55205bf5b6a --- /dev/null +++ b/spec/graphql/types/metadata_type_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe GitlabSchema.types['Metadata'] do + it { expect(described_class.graphql_name).to eq('Metadata') } +end diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index e1df6f9811d..fd75b8f700b 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -5,7 +5,7 @@ describe GitlabSchema.types['Query'] do expect(described_class.graphql_name).to eq('Query') end - it { is_expected.to have_graphql_fields(:project, :echo) } + it { is_expected.to have_graphql_fields(:project, :echo, :metadata) } describe 'project field' do subject { described_class.fields['project'] } @@ -20,4 +20,17 @@ describe GitlabSchema.types['Query'] do is_expected.to require_graphql_authorizations(:read_project) end end + + describe 'metadata field' do + subject { described_class.fields['metadata'] } + + it 'returns metadata' do + is_expected.to have_graphql_type(Types::MetadataType) + is_expected.to have_graphql_resolver(Resolvers::MetadataResolver) + end + + it 'authorizes with log_in' do + is_expected.to require_graphql_authorizations(:read_instance_metadata) + end + end end diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb index 30d68e7dc9d..12be3927e18 100644 --- a/spec/policies/global_policy_spec.rb +++ b/spec/policies/global_policy_spec.rb @@ -181,6 +181,18 @@ describe GlobalPolicy do end end + describe 'read instance metadata' do + context 'regular user' do + it { is_expected.to be_allowed(:read_instance_metadata) } + end + + context 'anonymous' do + let(:current_user) { nil } + + it { is_expected.not_to be_allowed(:read_instance_metadata) } + end + end + describe 'read instance statistics' do context 'regular user' do it { is_expected.to be_allowed(:read_instance_statistics) } diff --git a/spec/requests/api/graphql/metadata_query_spec.rb b/spec/requests/api/graphql/metadata_query_spec.rb new file mode 100644 index 00000000000..4c56c559cf9 --- /dev/null +++ b/spec/requests/api/graphql/metadata_query_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'getting project information' do + include GraphqlHelpers + + let(:query) { graphql_query_for('metadata', {}, all_graphql_fields_for('Metadata')) } + + context 'logged in' do + it 'returns version and revision' do + post_graphql(query, current_user: create(:user)) + + expect(graphql_errors).to be_nil + expect(graphql_data).to eq( + 'metadata' => { + 'version' => Gitlab::VERSION, + 'revision' => Gitlab.revision + } + ) + end + end + + context 'anonymous user' do + it 'returns nothing' do + post_graphql(query, current_user: nil) + + expect(graphql_errors).to be_nil + expect(graphql_data).to eq('metadata' => nil) + end + end +end diff --git a/spec/requests/api/version_spec.rb b/spec/requests/api/version_spec.rb index 38b618191fb..e06f8bbc095 100644 --- a/spec/requests/api/version_spec.rb +++ b/spec/requests/api/version_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe API::Version do - describe 'GET /version' do + shared_examples_for 'GET /version' do context 'when unauthenticated' do it 'returns authentication error' do get api('/version') @@ -22,4 +22,20 @@ describe API::Version do end end end + + context 'with graphql enabled' do + before do + stub_feature_flags(graphql: true) + end + + include_examples 'GET /version' + end + + context 'with graphql disabled' do + before do + stub_feature_flags(graphql: false) + end + + include_examples 'GET /version' + end end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index e468ee4676d..d9529262483 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -77,8 +77,9 @@ module GraphqlHelpers def query_graphql_field(name, attributes = {}, fields = nil) fields ||= all_graphql_fields_for(name.classify) attributes = attributes_to_graphql(attributes) + attributes = "(#{attributes})" if attributes.present? <<~QUERY - #{name}(#{attributes}) { + #{name}#{attributes} { #{fields} } QUERY -- GitLab From 01b1076bd869a5bbcbaf6df55e825cc39f705e2a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 5 Mar 2019 15:46:00 +0000 Subject: [PATCH 6/8] Apply suggestion to spec/graphql/types/query_type_spec.rb --- spec/graphql/types/query_type_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index fd75b8f700b..07c61ea7647 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -29,7 +29,7 @@ describe GitlabSchema.types['Query'] do is_expected.to have_graphql_resolver(Resolvers::MetadataResolver) end - it 'authorizes with log_in' do + it 'authorizes with read_instance_metadata' do is_expected.to require_graphql_authorizations(:read_instance_metadata) end end -- GitLab From e3eb241f5d71160db4535a4db19f0ea1944d2f0b Mon Sep 17 00:00:00 2001 From: Constance Okoghenun Date: Tue, 5 Mar 2019 18:08:39 +0000 Subject: [PATCH 7/8] Added tightLists option to copy_as_gfm markdown serializer This removes extraneous newlines when copying comments with an ordered list. --- .../javascripts/behaviors/markdown/copy_as_gfm.js | 4 +++- ...with-ordered-list-includes-extraneous-newlines.yml | 5 +++++ spec/features/markdown/copy_as_gfm_spec.rb | 11 ----------- spec/javascripts/behaviors/copy_as_gfm_spec.js | 4 ++-- 4 files changed, 10 insertions(+), 14 deletions(-) create mode 100644 changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js index 9482a9f166d..58cf057b2c2 100644 --- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js @@ -173,7 +173,9 @@ export class CopyAsGFM { wrapEl.appendChild(node.cloneNode(true)); const doc = DOMParser.fromSchema(schema.default).parse(wrapEl); - const res = markdownSerializer.default.serialize(doc); + const res = markdownSerializer.default.serialize(doc, { + tightLists: true, + }); return res; }) .catch(() => {}); diff --git a/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml b/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml new file mode 100644 index 00000000000..d0bb4225ce4 --- /dev/null +++ b/changelogs/unreleased/32714-copying-comment-with-ordered-list-includes-extraneous-newlines.yml @@ -0,0 +1,5 @@ +--- +title: Fixed "Copying comment with ordered list includes extraneous newlines" +merge_request: 25695 +author: +type: fixed diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb index 60ddb02da2c..c30ac9c4ae2 100644 --- a/spec/features/markdown/copy_as_gfm_spec.rb +++ b/spec/features/markdown/copy_as_gfm_spec.rb @@ -55,15 +55,10 @@ describe 'Copy as GFM', :js do To see how GitLab looks please see the [features page on our website](https://about.gitlab.com/features/). * Manage Git repositories with fine grained access controls that keep your code secure - * Perform code reviews and enhance collaboration with merge requests - * Complete continuous integration (CI) and CD pipelines to builds, test, and deploy your applications - * Each project can also have an issue tracker, issue board, and a wiki - * Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises - * Completely free and open source (MIT Expat license) GFM ) @@ -116,13 +111,11 @@ describe 'Copy as GFM', :js do <<~GFM, * [ ] Unchecked task - * [x] Checked task GFM <<~GFM 1. [ ] Unchecked ordered task - 1. [x] Checked ordered task GFM ) @@ -551,7 +544,6 @@ describe 'Copy as GFM', :js do <<~GFM, * List item - * List item 2 GFM @@ -565,7 +557,6 @@ describe 'Copy as GFM', :js do # nested lists <<~GFM, * Nested - * Lists GFM @@ -578,7 +569,6 @@ describe 'Copy as GFM', :js do <<~GFM, 1. Ordered list item - 1. Ordered list item 2 GFM @@ -592,7 +582,6 @@ describe 'Copy as GFM', :js do # nested ordered list <<~GFM, 1. Nested - 1. Ordered lists GFM diff --git a/spec/javascripts/behaviors/copy_as_gfm_spec.js b/spec/javascripts/behaviors/copy_as_gfm_spec.js index ca849f75860..d653fca0988 100644 --- a/spec/javascripts/behaviors/copy_as_gfm_spec.js +++ b/spec/javascripts/behaviors/copy_as_gfm_spec.js @@ -100,7 +100,7 @@ describe('CopyAsGFM', () => { simulateCopy(); setTimeout(() => { - const expectedGFM = '* List Item1\n\n* List Item2'; + const expectedGFM = '* List Item1\n* List Item2'; expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM); done(); @@ -114,7 +114,7 @@ describe('CopyAsGFM', () => { simulateCopy(); setTimeout(() => { - const expectedGFM = '1. List Item1\n\n1. List Item2'; + const expectedGFM = '1. List Item1\n1. List Item2'; expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM); done(); -- GitLab From ba98e91c067444e5af8dee392921126390af78b6 Mon Sep 17 00:00:00 2001 From: Andrew Fontaine Date: Tue, 5 Mar 2019 18:33:10 +0000 Subject: [PATCH 8/8] Add Component to Confirm Environment Rollback Ensure a vue.js component to confirm the re-deployment/rollback of an environment pops up when rollback/re-deploy has been clicked so the user must confirm their actions before accidentally rolling back or re-deploying an environment. Only on the `environment-table` view. --- .../components/confirm_rollback_modal.vue | 108 ++++++++++++++++++ .../components/environment_item.vue | 1 + .../components/environment_rollback.vue | 43 ++++--- .../components/environments_app.vue | 3 + .../environments/mixins/environments_mixin.js | 21 ++++ app/assets/stylesheets/framework/common.scss | 1 + .../_confirm_rollback_modal.html.haml | 23 ++++ app/views/projects/deployments/_rollback.haml | 3 +- ...-ask-for-confirmation-before-executing.yml | 5 + locale/gitlab.pot | 36 ++++++ .../confirm_rollback_modal_spec.js | 70 ++++++++++++ .../environments/environment_rollback_spec.js | 32 +++++- .../_confirm_rollback_modal_spec.html.rb | 63 ++++++++++ 13 files changed, 392 insertions(+), 17 deletions(-) create mode 100644 app/assets/javascripts/environments/components/confirm_rollback_modal.vue create mode 100644 app/views/projects/deployments/_confirm_rollback_modal.html.haml create mode 100644 changelogs/unreleased/27333-re-deploy-rollback-button-should-ask-for-confirmation-before-executing.yml create mode 100644 spec/javascripts/environments/confirm_rollback_modal_spec.js create mode 100644 spec/views/projects/deployments/_confirm_rollback_modal_spec.html.rb diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue new file mode 100644 index 00000000000..a8ee3f4ac10 --- /dev/null +++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue @@ -0,0 +1,108 @@ + + diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index 503c1b38f71..eb817beab9d 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -556,6 +556,7 @@ export default { diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue index 50c86af057c..266cdc42518 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.vue +++ b/app/assets/javascripts/environments/components/environment_rollback.vue @@ -5,29 +5,38 @@ * * Makes a post request when the button is clicked. */ +import { GlTooltipDirective, GlLoadingIcon, GlModalDirective, GlButton } from '@gitlab/ui'; import { s__ } from '~/locale'; -import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui'; import Icon from '~/vue_shared/components/icon.vue'; +import ConfirmRollbackModal from './confirm_rollback_modal.vue'; import eventHub from '../event_hub'; export default { components: { Icon, GlLoadingIcon, + GlButton, + ConfirmRollbackModal, }, directives: { GlTooltip: GlTooltipDirective, + GlModal: GlModalDirective, }, props: { - retryUrl: { - type: String, - default: '', - }, - isLastDeployment: { type: Boolean, default: true, }, + + environment: { + type: Object, + required: true, + }, + + retryUrl: { + type: String, + required: true, + }, }, data() { return { @@ -45,23 +54,31 @@ export default { methods: { onClick() { - this.isLoading = true; - - eventHub.$emit('postAction', { endpoint: this.retryUrl }); + eventHub.$emit('requestRollbackEnvironment', { + ...this.environment, + retryUrl: this.retryUrl, + isLastDeployment: this.isLastDeployment, + }); + eventHub.$on('rollbackEnvironment', environment => { + if (environment.id === this.environment.id) { + this.isLoading = true; + } + }); }, }, }; diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index aa2417d3194..6e55c3f901a 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -6,11 +6,13 @@ import eventHub from '../event_hub'; import environmentsMixin from '../mixins/environments_mixin'; import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin'; import StopEnvironmentModal from './stop_environment_modal.vue'; +import ConfirmRollbackModal from './confirm_rollback_modal.vue'; export default { components: { emptyState, StopEnvironmentModal, + ConfirmRollbackModal, }, mixins: [CIPaginationMixin, environmentsMixin], @@ -87,6 +89,7 @@ export default {