diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-24 12:07:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-24 12:07:44 +0300 |
commit | 6593f1f627938f22090dec5221476772d3ed581d (patch) | |
tree | ac5b9adf00f24f1d7cbc59c7d78f7c4fd06a0001 | |
parent | 2f369bd95866b7f623387ce2b6acf646df3d5222 (diff) |
Add latest changes from gitlab-org/gitlab@master
23 files changed, 194 insertions, 65 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index f19a7fec7c6..19aa96701d8 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -3,7 +3,8 @@ *.rake @gitlab-org/maintainers/rails-backend # Technical writing team are the default reviewers for everything in `doc/` -/doc/* @gl-docsteam +*.md @gl-docsteam +doc/ @gl-docsteam # Frontend maintainers should see everything in `app/assets/` app/assets/ @gitlab-org/maintainers/frontend diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 32a6ce3c719..54227249d1f 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1.76.0 +1.78.0 diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js index 318b7f77c7b..03c1b5a0169 100644 --- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js @@ -183,7 +183,7 @@ export class CopyAsGFM { } // Export CopyAsGFM as a global for rspec to access -// see /spec/features/copy_as_gfm_spec.rb +// see /spec/features/markdown/copy_as_gfm_spec.rb if (process.env.NODE_ENV !== 'production') { window.CopyAsGFM = CopyAsGFM; } diff --git a/app/assets/javascripts/behaviors/markdown/editor_extensions.js b/app/assets/javascripts/behaviors/markdown/editor_extensions.js index 8bd2145db1c..308e31e7047 100644 --- a/app/assets/javascripts/behaviors/markdown/editor_extensions.js +++ b/app/assets/javascripts/behaviors/markdown/editor_extensions.js @@ -53,7 +53,7 @@ import InlineHTML from './marks/inline_html'; // The nodes and marks referenced here transform that same HTML to GFM to be copied to the clipboard. // Every filter in lib/banzai/pipeline/gfm_pipeline.rb that generates HTML // from GFM should have a node or mark here. -// The GFM-to-HTML-to-GFM cycle is tested in spec/features/copy_as_gfm_spec.rb. +// The GFM-to-HTML-to-GFM cycle is tested in spec/features/markdown/copy_as_gfm_spec.rb. export default [ new Doc(), diff --git a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js index d1aba99ac22..188ab1769a4 100644 --- a/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js +++ b/app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js @@ -12,6 +12,7 @@ function cleanSuggestionLine(line = {}) { return { ...line, text: trimFirstCharOfLineContent(line.text), + rich_text: trimFirstCharOfLineContent(line.rich_text), }; } diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue index c09bdfec250..97d93eaaf3f 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue @@ -24,7 +24,8 @@ export default { {{ line.new_line }} </td> <td class="line_content" :class="lineType"> - <span v-if="line.text">{{ line.text }}</span> + <span v-if="line.rich_text" v-html="line.rich_text"></span> + <span v-else-if="line.text">{{ line.text }}</span> <!-- TODO: replace this hack with zero-width whitespace when we have rich_text from BE --> <span v-else>​</span> </td> diff --git a/app/serializers/suggestion_entity.rb b/app/serializers/suggestion_entity.rb index 2dd62e19e29..4fb19fbc074 100644 --- a/app/serializers/suggestion_entity.rb +++ b/app/serializers/suggestion_entity.rb @@ -4,7 +4,9 @@ class SuggestionEntity < API::Entities::Suggestion include RequestAwareEntity unexpose :from_line, :to_line, :from_content, :to_content - expose :diff_lines, using: DiffLineEntity + expose :diff_lines, using: DiffLineEntity do |suggestion| + Gitlab::Diff::Highlight.new(suggestion.diff_lines).highlight + end expose :current_user do expose :can_apply do |suggestion| Ability.allowed?(current_user, :apply_suggestion, suggestion) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index a14e0515a1f..a781eacc40e 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -84,7 +84,9 @@ module QuickActions # rubocop: enable CodeReuse/ActiveRecord def find_milestones(project, params = {}) - MilestonesFinder.new(params.merge(project_ids: [project.id], group_ids: [project.group&.id])).execute + group_ids = project.group.self_and_ancestors.select(:id) if project.group + + MilestonesFinder.new(params.merge(project_ids: [project.id], group_ids: group_ids)).execute end def parent diff --git a/changelogs/unreleased/25250-can-t-use-quick-action-to-set-milestone-when-the-project-only-has-m.yml b/changelogs/unreleased/25250-can-t-use-quick-action-to-set-milestone-when-the-project-only-has-m.yml new file mode 100644 index 00000000000..6fba3f2b96f --- /dev/null +++ b/changelogs/unreleased/25250-can-t-use-quick-action-to-set-milestone-when-the-project-only-has-m.yml @@ -0,0 +1,5 @@ +--- +title: Fix milestone quick action to handle ancestor group milestones +merge_request: 22231 +author: +type: fixed diff --git a/changelogs/unreleased/26543-add-word-diff-highlight-to-rich-text.yml b/changelogs/unreleased/26543-add-word-diff-highlight-to-rich-text.yml new file mode 100644 index 00000000000..cea1158d9ef --- /dev/null +++ b/changelogs/unreleased/26543-add-word-diff-highlight-to-rich-text.yml @@ -0,0 +1,5 @@ +--- +title: Apply word-diff highlighting to Suggestions +merge_request: 22182 +author: +type: changed diff --git a/changelogs/unreleased/dz-move-repo-routes-2.yml b/changelogs/unreleased/dz-move-repo-routes-2.yml new file mode 100644 index 00000000000..349c2a9f480 --- /dev/null +++ b/changelogs/unreleased/dz-move-repo-routes-2.yml @@ -0,0 +1,5 @@ +--- +title: Copy repository route under - scope +merge_request: 22092 +author: +type: changed diff --git a/changelogs/unreleased/gitaly-cache-invalidator-ff.yml b/changelogs/unreleased/gitaly-cache-invalidator-ff.yml new file mode 100644 index 00000000000..191dce3f950 --- /dev/null +++ b/changelogs/unreleased/gitaly-cache-invalidator-ff.yml @@ -0,0 +1,5 @@ +--- +title: Add back feature flag for cache invalidator +merge_request: 22106 +author: +type: changed diff --git a/config/routes/project.rb b/config/routes/project.rb index 0cc8e83de2c..ddd1693ef02 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -274,8 +274,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do end end - # The wiki routing contains wildcard characters so + # The wiki and repository routing contains wildcard characters so # its preferable to keep it below all other project routes + draw :repository_scoped draw :wiki end # End of the /-/ scope. @@ -481,6 +482,13 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do # its preferable to keep it below all other project routes draw :repository + # To ensure an old unscoped routing is used for the UI we need to + # add prefix 'as' to the scope routing and place it below original routing. + # Issue https://gitlab.com/gitlab-org/gitlab/issues/118849 + scope '-', as: 'scoped' do + draw :repository + end + # All new routes should go under /-/ scope. # Look for scope '-' at the top of the file. # rubocop: enable Cop/PutProjectRoutesUnderScope diff --git a/config/routes/repository.rb b/config/routes/repository.rb index 4815575ba9f..d4805b67a5c 100644 --- a/config/routes/repository.rb +++ b/config/routes/repository.rb @@ -39,32 +39,6 @@ scope format: false do end end - scope path: '-', constraints: { id: Gitlab::PathRegex.git_reference_regex } do - resources :network, only: [:show] - - resources :graphs, only: [:show] do - member do - get :charts - get :commits - get :ci - get :languages - end - end - - get '/branches/:state', to: 'branches#index', as: :branches_filtered, constraints: { state: /active|stale|all/ } - resources :branches, only: [:index, :new, :create, :destroy] do - get :diverging_commit_counts, on: :collection - end - - delete :merged_branches, controller: 'branches', action: :destroy_all_merged - resources :tags, only: [:index, :show, :new, :create, :destroy] do - resource :release, controller: 'tags/releases', only: [:edit, :update] - end - - resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex } - resources :protected_tags, only: [:index, :show, :create, :update, :destroy] - end - scope constraints: { id: /[^\0]+/ } do scope controller: :blob do get '/new/*id', action: :new, as: :new_blob diff --git a/config/routes/repository_scoped.rb b/config/routes/repository_scoped.rb new file mode 100644 index 00000000000..c6343039d62 --- /dev/null +++ b/config/routes/repository_scoped.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# All routing related to repository browsing +# that is already under /-/ scope only + +# Don't use format parameter as file extension (old 3.0.x behavior) +# See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments +scope format: false do + scope constraints: { id: Gitlab::PathRegex.git_reference_regex } do + resources :network, only: [:show] + + resources :graphs, only: [:show] do + member do + get :charts + get :commits + get :ci + get :languages + end + end + + get '/branches/:state', to: 'branches#index', as: :branches_filtered, constraints: { state: /active|stale|all/ } + resources :branches, only: [:index, :new, :create, :destroy] do + get :diverging_commit_counts, on: :collection + end + + delete :merged_branches, controller: 'branches', action: :destroy_all_merged + resources :tags, only: [:index, :show, :new, :create, :destroy] do + resource :release, controller: 'tags/releases', only: [:edit, :update] + end + + resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex } + resources :protected_tags, only: [:index, :show, :create, :update, :destroy] + end +end diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md index 81edd9eac34..666e6c8d7ad 100644 --- a/doc/user/admin_area/settings/usage_statistics.md +++ b/doc/user/admin_area/settings/usage_statistics.md @@ -10,7 +10,7 @@ to perform various actions. All statistics are opt-out, you can enable/disable them from the admin panel under **Admin area > Settings > Metrics and profiling > Usage statistics**. -## Version check **(CORE ONLY)** +## Version Check **(CORE ONLY)** If enabled, version check will inform you if a new version is available and the importance of it through a status. This is shown on the help page (i.e. `/help`) @@ -33,7 +33,23 @@ secure. If you disable version check, this information will not be collected. Enable or disable the version check at **Admin area > Settings > Metrics and profiling > Usage statistics**. -## Usage ping **(CORE ONLY)** +### Request flow example + +The following example shows a basic request/response flow between the self-managed GitLab instance +and the GitLab Version Application: + +```mermaid +sequenceDiagram + participant GitLab instance + participant Version Application + GitLab instance->>Version Application: Is there a version update? + loop Version Check + Version Application->>Version Application: Record version info + end + Version Application->>GitLab instance: Response (PNG/SVG) +``` + +## Usage Ping **(CORE ONLY)** > [Introduced][ee-557] in GitLab Enterprise Edition 8.10. More statistics [were added][ee-735] in GitLab Enterprise Edition @@ -52,7 +68,32 @@ You can view the exact JSON payload in the administration panel. To view the pay 1. Expand **Settings** in the left sidebar and click on **Metrics and profiling**. 1. Expand **Usage statistics** and click on the **Preview payload** button. -You can see how [the usage ping data maps to different stages of the product](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv). +You can see how [the usage ping data maps to different stages of the product](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/version_usage_stats_to_stage_mappings.csv). + +### Request flow example + +The following example shows a basic request/response flow between the self-managed GitLab instance, GitLab Version Application, +GitLab License Application and Salesforce: + +```mermaid +sequenceDiagram + participant GitLab instance + participant Version Application + participant License Application + participant Salesforce + GitLab instance->>Version Application: Usage Ping data + loop Process Usage Data + Version Application->>Version Application: Parse Usage Data + Version Application->>Version Application: Record Usage Data + Version Application->>Version Application: Update license ping time + end + Version Application-xLicense Application: Request Zuora subscription id + License Application-xVersion Application: Zuora subscription id + Version Application-xSalesforce: Request Zuora account id by Zuora subscription id + Salesforce-xVersion Application: Zuora account id + Version Application-xSalesforce: Usage data for the Zuora account + Version Application->>GitLab instance: Conversational Development Index +``` ### Deactivate the usage ping diff --git a/lib/feature/gitaly.rb b/lib/feature/gitaly.rb index 625db1fce32..2bd55c36a03 100644 --- a/lib/feature/gitaly.rb +++ b/lib/feature/gitaly.rb @@ -7,6 +7,7 @@ class Feature # Server feature flags should use '_' to separate words. SERVER_FEATURE_FLAGS = %w[ + cache_invalidator inforef_uploadpack_cache get_tag_messages_go filter_shas_with_signatures_go diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js index c8deac1c086..8e6ac6a5fab 100644 --- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js +++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js @@ -7,8 +7,8 @@ const oldLine = { meta_data: null, new_line: null, old_line: 5, - rich_text: '-oldtext', - text: '-oldtext', + rich_text: 'oldrichtext', + text: 'oldplaintext', type: 'old', }; @@ -18,8 +18,8 @@ const newLine = { meta_data: null, new_line: 6, old_line: null, - rich_text: '-newtext', - text: '-newtext', + rich_text: 'newrichtext', + text: 'newplaintext', type: 'new', }; @@ -42,14 +42,46 @@ describe('SuggestionDiffRow', () => { wrapper.destroy(); }); - it('renders correctly', () => { - factory({ - propsData: { - line: oldLine, - }, + describe('renders correctly', () => { + it('has the right classes on the wrapper', () => { + factory({ + propsData: { + line: oldLine, + }, + }); + + expect(wrapper.is('.line_holder')).toBe(true); + }); + + it('renders the rich text when it is available', () => { + factory({ + propsData: { + line: newLine, + }, + }); + + expect(wrapper.find('td.line_content').text()).toEqual('newrichtext'); }); - expect(wrapper.is('.line_holder')).toBe(true); + it('renders the plain text when it is available but rich text is not', () => { + factory({ + propsData: { + line: Object.assign({}, newLine, { rich_text: undefined }), + }, + }); + + expect(wrapper.find('td.line_content').text()).toEqual('newplaintext'); + }); + + it('renders a zero-width space when it has no plain or rich texts', () => { + factory({ + propsData: { + line: Object.assign({}, newLine, { rich_text: undefined, text: undefined }), + }, + }); + + expect(wrapper.find('td.line_content').text()).toEqual('\u200B'); + }); }); describe('when passed line has type old', () => { diff --git a/spec/models/concerns/safe_url_spec.rb b/spec/models/concerns/safe_url_spec.rb index 0ad26660a60..e523e6a15e4 100644 --- a/spec/models/concerns/safe_url_spec.rb +++ b/spec/models/concerns/safe_url_spec.rb @@ -4,17 +4,19 @@ require 'spec_helper' describe SafeUrl do describe '#safe_url' do - class SafeUrlTestClass - include SafeUrl + let(:safe_url_test_class) do + Class.new do + include SafeUrl - attr_reader :url + attr_reader :url - def initialize(url) - @url = url + def initialize(url) + @url = url + end end end - let(:test_class) { SafeUrlTestClass.new(url) } + let(:test_class) { safe_url_test_class.new(url) } let(:url) { 'http://example.com' } subject { test_class.safe_url } diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb index ecbb81294a0..df55e9ad849 100644 --- a/spec/requests/api/internal/base_spec.rb +++ b/spec/requests/api/internal/base_spec.rb @@ -326,7 +326,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) - expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true') + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true', 'gitaly-feature-cache-invalidator' => 'true') expect(user.reload.last_activity_on).to eql(Date.today) end end @@ -346,7 +346,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) - expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true') + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true', 'gitaly-feature-cache-invalidator' => 'true') expect(user.reload.last_activity_on).to be_nil end end @@ -588,7 +588,7 @@ describe API::Internal::Base do expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path) expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage)) expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage)) - expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true') + expect(json_response["gitaly"]["features"]).to eq('gitaly-feature-inforef-uploadpack-cache' => 'true', 'gitaly-feature-get-tag-messages-go' => 'true', 'gitaly-feature-filter-shas-with-signatures-go' => 'true', 'gitaly-feature-cache-invalidator' => 'true') end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index b736d58bf58..efd7d3f3742 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -579,6 +579,10 @@ describe 'project routing' do namespace_id: 'gitlab', project_id: 'gitlabhq', id: "blob/master/blob/#{newline_file}" }) end + + it 'to #show from scope routing' do + expect(get('/gitlab/gitlabhq/-/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + end end # project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /[^\0]+/, project_id: /[^\/]+/} @@ -596,6 +600,10 @@ describe 'project routing' do namespace_id: 'gitlab', project_id: 'gitlabhq', id: "master/#{newline_file}" }) end + + it 'to #show from scope routing' do + expect(get('/gitlab/gitlabhq/-/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + end end # project_find_file GET /:namespace_id/:project_id/find_file/*id(.:format) projects/find_file#show {:id=>/[^\0]+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/html/} diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index b105e1e40ce..b2576cae575 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -856,9 +856,10 @@ describe QuickActions::InterpretService do end context 'only group milestones available' do - let(:group) { create(:group) } + let(:ancestor_group) { create(:group) } + let(:group) { create(:group, parent: ancestor_group) } let(:project) { create(:project, :public, namespace: group) } - let(:milestone) { create(:milestone, group: group, title: '10.0') } + let(:milestone) { create(:milestone, group: ancestor_group, title: '10.0') } it_behaves_like 'milestone command' do let(:content) { "/milestone %#{milestone.title}" } diff --git a/spec/validators/qualified_domain_array_validator_spec.rb b/spec/validators/qualified_domain_array_validator_spec.rb index ab6cca4b671..664048c7544 100644 --- a/spec/validators/qualified_domain_array_validator_spec.rb +++ b/spec/validators/qualified_domain_array_validator_spec.rb @@ -3,18 +3,19 @@ require 'spec_helper' describe QualifiedDomainArrayValidator do - class QualifiedDomainArrayValidatorTestClass - include ActiveModel::Validations + let(:qualified_domain_array_validator_test_class) do + Class.new do + include ActiveModel::Validations - attr_accessor :domain_array + attr_accessor :domain_array - def initialize(domain_array) - self.domain_array = domain_array + def initialize(domain_array) + self.domain_array = domain_array + end end end - let!(:record) do - QualifiedDomainArrayValidatorTestClass.new(['gitlab.com']) + qualified_domain_array_validator_test_class.new(['gitlab.com']) end subject { validator.validate(record) } |