diff options
31 files changed, 284 insertions, 55 deletions
diff --git a/app/assets/javascripts/mr_tabs_popover/components/popover.vue b/app/assets/javascripts/mr_tabs_popover/components/popover.vue new file mode 100644 index 00000000000..da1e1e70993 --- /dev/null +++ b/app/assets/javascripts/mr_tabs_popover/components/popover.vue @@ -0,0 +1,64 @@ +<script> +import { GlPopover, GlButton, GlLink } from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; +import axios from '~/lib/utils/axios_utils'; + +export default { + components: { + GlPopover, + GlButton, + GlLink, + Icon, + }, + props: { + dismissEndpoint: { + type: String, + required: true, + }, + featureId: { + type: String, + required: true, + }, + }, + data() { + return { + showPopover: false, + }; + }, + mounted() { + setTimeout(() => { + this.showPopover = true; + }, 2000); + }, + methods: { + onDismiss() { + this.showPopover = false; + + axios.post(this.dismissEndpoint, { + feature_name: this.featureId, + }); + }, + }, +}; +</script> + +<template> + <gl-popover target="#diffs-tab" placement="bottom" :show="showPopover"> + <p class="mb-2"> + {{ + __( + 'Now you can access the merge request navigation tabs at the top, where they’re easier to find.', + ) + }} + </p> + <p> + <gl-link href="https://gitlab.com/gitlab-org/gitlab/issues/36125" target="_blank"> + {{ __('More information and share feedback') }} + <icon name="external-link" :size="10" /> + </gl-link> + </p> + <gl-button variant="primary" size="sm" @click="onDismiss"> + {{ __('Got it') }} + </gl-button> + </gl-popover> +</template> diff --git a/app/assets/javascripts/mr_tabs_popover/index.js b/app/assets/javascripts/mr_tabs_popover/index.js new file mode 100644 index 00000000000..9ee0ba046f0 --- /dev/null +++ b/app/assets/javascripts/mr_tabs_popover/index.js @@ -0,0 +1,12 @@ +import Vue from 'vue'; +import Popover from './components/popover.vue'; + +export default el => + new Vue({ + el, + render(createElement) { + return createElement(Popover, { + props: { dismissEndpoint: el.dataset.dismissEndpoint, featureId: el.dataset.featureId }, + }); + }, + }); diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js index 16034313af2..1f8befc07c8 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js @@ -6,6 +6,7 @@ import howToMerge from '~/how_to_merge'; import initPipelines from '~/commit/pipelines/pipelines_bundle'; import initVueIssuableSidebarApp from '~/issuable_sidebar/sidebar_bundle'; import initSourcegraph from '~/sourcegraph'; +import initPopover from '~/mr_tabs_popover'; import initWidget from '../../../vue_merge_request_widget'; export default function() { @@ -21,4 +22,10 @@ export default function() { howToMerge(); initWidget(); initSourcegraph(); + + const tabHighlightEl = document.querySelector('.js-tabs-feature-highlight'); + + if (tabHighlightEl) { + initPopover(tabHighlightEl); + } } diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js index 8d6a3781048..4598626718c 100644 --- a/app/assets/javascripts/persistent_user_callout.js +++ b/app/assets/javascripts/persistent_user_callout.js @@ -6,8 +6,8 @@ import Flash from './flash'; const DEFERRED_LINK_CLASS = 'deferred-link'; export default class PersistentUserCallout { - constructor(container) { - const { dismissEndpoint, featureId, deferLinks } = container.dataset; + constructor(container, options = container.dataset) { + const { dismissEndpoint, featureId, deferLinks } = options; this.container = container; this.dismissEndpoint = dismissEndpoint; this.featureId = featureId; @@ -53,11 +53,11 @@ export default class PersistentUserCallout { }); } - static factory(container) { + static factory(container, options) { if (!container) { return undefined; } - return new PersistentUserCallout(container); + return new PersistentUserCallout(container, options); } } diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 899ab70d1aa..46db3b78fd0 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true module MergeRequestsHelper + include Gitlab::Utils::StrongMemoize + def new_mr_path_from_push_event(event) target_project = event.project.default_merge_request_target project_new_merge_request_path( @@ -168,6 +170,12 @@ module MergeRequestsHelper current_user.fork_of(project) end end + + def mr_tabs_position_enabled? + strong_memoize(:mr_tabs_position_enabled) do + Feature.enabled?(:mr_tabs_position, @project, default_enabled: true) + end + end end MergeRequestsHelper.prepend_if_ee('EE::MergeRequestsHelper') diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb index cae3ec5f8d0..11b78b8fd59 100644 --- a/app/helpers/user_callouts_helper.rb +++ b/app/helpers/user_callouts_helper.rb @@ -4,6 +4,7 @@ module UserCalloutsHelper GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration' GCP_SIGNUP_OFFER = 'gcp_signup_offer' SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed' + TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight' def show_gke_cluster_integration_callout?(project) can?(current_user, :create_cluster, project) && @@ -25,6 +26,10 @@ module UserCalloutsHelper !user_dismissed?(SUGGEST_POPOVER_DISMISSED) end + def show_tabs_feature_highlight? + !user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test? + end + private def user_dismissed?(feature_name) diff --git a/app/models/user_callout_enums.rb b/app/models/user_callout_enums.rb index e9f25d833d0..ef0b2407e23 100644 --- a/app/models/user_callout_enums.rb +++ b/app/models/user_callout_enums.rb @@ -14,7 +14,8 @@ module UserCalloutEnums gke_cluster_integration: 1, gcp_signup_offer: 2, cluster_security_warning: 3, - suggest_popover_dismissed: 9 + suggest_popover_dismissed: 9, + tabs_position_highlight: 10 } end end diff --git a/app/views/award_emoji/_awards_block.html.haml b/app/views/award_emoji/_awards_block.html.haml index 60ca7e4e267..793ddef2c58 100644 --- a/app/views/award_emoji/_awards_block.html.haml +++ b/app/views/award_emoji/_awards_block.html.haml @@ -17,3 +17,4 @@ %span{ class: "award-control-icon award-control-icon-positive" }= sprite_icon('smiley') %span{ class: "award-control-icon award-control-icon-super-positive" }= sprite_icon('smile') = icon('spinner spin', class: "award-control-icon award-control-icon-loading") + = yield diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml index f53bd2b5e4d..1b799477093 100644 --- a/app/views/layouts/nav/_breadcrumbs.html.haml +++ b/app/views/layouts/nav/_breadcrumbs.html.haml @@ -2,7 +2,7 @@ - hide_top_links = @hide_top_links || false %nav.breadcrumbs{ role: "navigation", class: [container, @content_class] } - .breadcrumbs-container + .breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border && mr_tabs_position_enabled?) } - if defined?(@left_sidebar) = button_tag class: 'toggle-mobile-nav', type: 'button' do %span.sr-only= _("Open sidebar") diff --git a/app/views/projects/merge_requests/_awards_block.html.haml b/app/views/projects/merge_requests/_awards_block.html.haml new file mode 100644 index 00000000000..1eab28a2ff3 --- /dev/null +++ b/app/views/projects/merge_requests/_awards_block.html.haml @@ -0,0 +1,5 @@ +.content-block.content-block-small.emoji-list-container.js-noteable-awards + = render 'award_emoji/awards_block', awardable: @merge_request, inline: true do + - if mr_tabs_position_enabled? + .ml-auto.mt-auto.mb-auto + = render "projects/merge_requests/discussion_filter" diff --git a/app/views/projects/merge_requests/_description.html.haml b/app/views/projects/merge_requests/_description.html.haml new file mode 100644 index 00000000000..354a384b647 --- /dev/null +++ b/app/views/projects/merge_requests/_description.html.haml @@ -0,0 +1,9 @@ +%div + - if @merge_request.description.present? + .description.qa-description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' } + .md + = markdown_field(@merge_request, :description) + %textarea.hidden.js-task-list-field + = @merge_request.description + + = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') diff --git a/app/views/projects/merge_requests/_discussion_filter.html.haml b/app/views/projects/merge_requests/_discussion_filter.html.haml new file mode 100644 index 00000000000..96886661a8d --- /dev/null +++ b/app/views/projects/merge_requests/_discussion_filter.html.haml @@ -0,0 +1,2 @@ +#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@merge_request), + notes_filters: UserPreference.notes_filters.to_json } } diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml index 4f09f47d795..ec78b040167 100644 --- a/app/views/projects/merge_requests/_mr_box.html.haml +++ b/app/views/projects/merge_requests/_mr_box.html.haml @@ -1,13 +1,6 @@ -.detail-page-description - %h2.title.qa-title +.detail-page-description{ class: ("py-2" if mr_tabs_position_enabled?) } + %h2.title.qa-title{ class: ("mb-0" if mr_tabs_position_enabled?) } = markdown_field(@merge_request, :title) - %div - - if @merge_request.description.present? - .description.qa-description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' } - .md - = markdown_field(@merge_request, :description) - %textarea.hidden.js-task-list-field - = @merge_request.description - - = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') + - unless mr_tabs_position_enabled? + = render "projects/merge_requests/description" diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index 552f8dc173a..d1e8dc3a834 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -1,3 +1,4 @@ +- @no_breadcrumb_border = true - can_update_merge_request = can?(current_user, :update_merge_request, @merge_request) - can_reopen_merge_request = can?(current_user, :reopen_merge_request, @merge_request) - state_human_name, state_icon_name = state_name_with_icon(@merge_request) @@ -6,7 +7,7 @@ .alert.alert-danger The source project of this merge request has been removed. -.detail-page-header +.detail-page-header{ class: ("border-bottom-0 pt-0 pb-0" if mr_tabs_position_enabled?) } .detail-page-header-body .issuable-status-box.status-box{ class: status_box_class(@merge_request) } = sprite_icon(state_icon_name, size: 16, css_class: 'd-block d-sm-none') diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml new file mode 100644 index 00000000000..f056189fec0 --- /dev/null +++ b/app/views/projects/merge_requests/_widget.html.haml @@ -0,0 +1,13 @@ +- if @merge_request.source_branch_exists? + = render "projects/merge_requests/how_to_merge" + += javascript_tag nonce: true do + :plain + window.gl = window.gl || {}; + window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)} + + window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}'; + window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}'; + window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.html', anchor: 'security-approvals-in-merge-requests-ultimate')}'; + +#js-vue-mr-widget.mr-widget diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index c2bc5376fd7..310cd355d22 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -14,56 +14,54 @@ .merge-request-details.issuable-details{ data: { id: @merge_request.project.id } } = render "projects/merge_requests/mr_box" - - if @merge_request.source_branch_exists? - = render "projects/merge_requests/how_to_merge" - - = javascript_tag nonce: true do - :plain - window.gl = window.gl || {}; - window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)} - - window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}'; - window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}'; - window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.html', anchor: 'security-approvals-in-merge-requests-ultimate')}'; - - #js-vue-mr-widget.mr-widget - - .content-block.content-block-small.emoji-list-container.js-noteable-awards - = render 'award_emoji/awards_block', awardable: @merge_request, inline: true + - unless mr_tabs_position_enabled? + = render "projects/merge_requests/widget" + = render "projects/merge_requests/awards_block" .merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') } .merge-request-tabs-container %ul.merge-request-tabs.nav-tabs.nav.nav-links - %li.notes-tab{ data: { qa_selector: 'notes_tab'} } + = render "projects/merge_requests/tabs/tab", class: "notes-tab", qa_selector: "notes_tab" do = tab_link_for @merge_request, :show, force_link: @commit.present? do - = _("Discussion") + - if mr_tabs_position_enabled? + = _("Overview") + - else + = _("Discussion") %span.badge.badge-pill= @merge_request.related_notes.user.count - if @merge_request.source_project - %li.commits-tab + = render "projects/merge_requests/tabs/tab", name: "commits", class: "commits-tab" do = tab_link_for @merge_request, :commits do = _("Commits") %span.badge.badge-pill= @commits_count - if number_of_pipelines.nonzero? - %li.pipelines-tab + = render "projects/merge_requests/tabs/tab", name: "pipelines", class: "pipelines-tab" do = tab_link_for @merge_request, :pipelines do = _("Pipelines") %span.badge.badge-pill.js-pipelines-mr-count= number_of_pipelines - %li.diffs-tab.qa-diffs-tab + = render "projects/merge_requests/tabs/tab", name: "diffs", class: "diffs-tab qa-diffs-tab", id: "diffs-tab" do = tab_link_for @merge_request, :diffs do = _("Changes") %span.badge.badge-pill= @merge_request.diff_size + - if mr_tabs_position_enabled? && show_tabs_feature_highlight? + .js-tabs-feature-highlight{ data: { dismiss_endpoint: user_callouts_path, feature_id: UserCalloutsHelper::TABS_POSITION_HIGHLIGHT } } .d-flex.flex-wrap.align-items-center.justify-content-lg-end - #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@merge_request), - notes_filters: UserPreference.notes_filters.to_json } } + - unless mr_tabs_position_enabled? + = render "projects/merge_requests/discussion_filter" #js-vue-discussion-counter .tab-content#diff-notes-app #js-diff-file-finder - #notes.notes.tab-pane.voting_notes + = render "projects/merge_requests/tabs/pane", id: "notes", class: "notes voting_notes" do .row %section.col-md-12 %script.js-notes-data{ type: "application/json" }= initial_notes_data(true).to_json.html_safe .issuable-discussion.js-vue-notes-event + - if mr_tabs_position_enabled? + - if @merge_request.description.present? + .detail-page-description + = render "projects/merge_requests/description" + = render "projects/merge_requests/widget" + = render "projects/merge_requests/awards_block" #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request).to_json, noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'), noteable_type: 'MergeRequest', @@ -71,12 +69,12 @@ help_page_path: suggest_changes_help_path, current_user_data: @current_user_data} } - #commits.commits.tab-pane + = render "projects/merge_requests/tabs/pane", name: "commits", id: "commits", class: "commits" do -# This tab is always loaded via AJAX - #pipelines.pipelines.tab-pane + = render "projects/merge_requests/tabs/pane", name: "pipelines", id: "pipelines", class: "pipelines" do - if number_of_pipelines.nonzero? = render 'projects/commit/pipelines_list', disable_initialization: true, endpoint: pipelines_project_merge_request_path(@project, @merge_request) - #js-diffs-app.diffs.tab-pane{ data: { "is-locked" => @merge_request.discussion_locked?, + = render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: { "is-locked": @merge_request.discussion_locked?, endpoint: diffs_project_merge_request_path(@project, @merge_request, 'json', request.query_parameters), endpoint_metadata: diffs_metadata_project_json_merge_request_path(@project, @merge_request, 'json', request.query_parameters), endpoint_batch: diffs_batch_project_json_merge_request_path(@project, @merge_request, 'json', request.query_parameters), @@ -87,7 +85,7 @@ is_fluid_layout: fluid_layout.to_s, dismiss_endpoint: user_callouts_path, show_suggest_popover: show_suggest_popover?.to_s, - show_whitespace_default: @show_whitespace_default.to_s } } + show_whitespace_default: @show_whitespace_default.to_s } .mr-loading-status = spinner diff --git a/app/views/projects/merge_requests/tabs/_pane.html.haml b/app/views/projects/merge_requests/tabs/_pane.html.haml new file mode 100644 index 00000000000..1a88d5f5134 --- /dev/null +++ b/app/views/projects/merge_requests/tabs/_pane.html.haml @@ -0,0 +1,7 @@ +- tab_name = local_assigns.fetch(:name, nil) +- tab_id = local_assigns.fetch(:id, nil) +- tab_class = local_assigns.fetch(:class, nil) +- tab_data = local_assigns.fetch(:data, nil) + +.tab-pane{ id: tab_id, class: tab_class, style: ("display: block" if params[:tab] == tab_name), data: tab_data } + = yield diff --git a/app/views/projects/merge_requests/tabs/_tab.html.haml b/app/views/projects/merge_requests/tabs/_tab.html.haml new file mode 100644 index 00000000000..dcd8db90509 --- /dev/null +++ b/app/views/projects/merge_requests/tabs/_tab.html.haml @@ -0,0 +1,7 @@ +- tab_name = local_assigns.fetch(:name, nil) +- tab_class = local_assigns.fetch(:class, nil) +- qa_selector = local_assigns.fetch(:qa_selector, nil) +- id = local_assigns.fetch(:id, nil) + +%li{ class: [tab_class, ("active" if params[:tab] == tab_name)], id: id, data: { qa_selector: qa_selector } } + = yield diff --git a/changelogs/unreleased/34685-Pages-template-jekyll-outdated-and-not-working-as-expected.yml b/changelogs/unreleased/34685-Pages-template-jekyll-outdated-and-not-working-as-expected.yml new file mode 100644 index 00000000000..0ed03916829 --- /dev/null +++ b/changelogs/unreleased/34685-Pages-template-jekyll-outdated-and-not-working-as-expected.yml @@ -0,0 +1,5 @@ +--- +title: Updated jekyll project_template +merge_request: 20090 +author: Marc Schwede +type: other diff --git a/changelogs/unreleased/Updated-hexo-project_template.yml b/changelogs/unreleased/Updated-hexo-project_template.yml new file mode 100644 index 00000000000..4777220ca55 --- /dev/null +++ b/changelogs/unreleased/Updated-hexo-project_template.yml @@ -0,0 +1,5 @@ +--- +title: Updated hexo project_template +merge_request: 20105 +author: Marc Schwede +type: other diff --git a/changelogs/unreleased/Updated-hugo-project_template.yml b/changelogs/unreleased/Updated-hugo-project_template.yml new file mode 100644 index 00000000000..58488dfcb4c --- /dev/null +++ b/changelogs/unreleased/Updated-hugo-project_template.yml @@ -0,0 +1,5 @@ +--- +title: Updated hugo project_template +merge_request: 20109 +author: Marc Schwede +type: other diff --git a/changelogs/unreleased/ph-33813-moveMergeRequestDescription.yml b/changelogs/unreleased/ph-33813-moveMergeRequestDescription.yml new file mode 100644 index 00000000000..0fa53a94946 --- /dev/null +++ b/changelogs/unreleased/ph-33813-moveMergeRequestDescription.yml @@ -0,0 +1,5 @@ +--- +title: Move merge request description into discussions tab +merge_request: 18940 +author: +type: changed diff --git a/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png b/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png Binary files differnew file mode 100644 index 00000000000..9284e58f456 --- /dev/null +++ b/doc/user/project/merge_requests/img/merge_request_tab_position_v12_6.png diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 1ca8c882ac7..203a2949243 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -40,6 +40,40 @@ B. Consider you're a web developer writing a webpage for your company's website: 1. Once approved, your merge request is [squashed and merged](squash_and_merge.md), and [deployed to staging with GitLab Pages](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) 1. Your production team [cherry picks](cherry_pick_changes.md) the merge commit into production +## Overview + +Merge requests (aka "MRs") display a great deal of information about the changes proposed. +The body of an MR contains its description, along with its widget (displaying information +about CI/CD pipelines, when present), followed by the discussion threads of the people +collaborating with that MR. + +MRs also contain navigation tabs from which you can see the discussion happening on the thread, +the list of commits, the list of pipelines and jobs, the code changes and inline code reviews. + +## Merge request navigation tabs at the top + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/33813) in GitLab 12.6. This positioning is experimental. + +So far, the navigation tabs present in merge requests to display **Discussion**, +**Commits**, **Pipelines**, and **Changes** were located after the merge request +widget. + +To facilitate this navigation without having to scroll up and down through the page +to find these tabs, based on user feedback, we are experimenting with a new positioning +of these tabs. They are now located at the top of the merge request, with a new +**Overview** tab, containing the description of the merge request followed by the +widget. Next to **Overview**, you can find **Pipelines**, **Commits**, and **Changes**. + +![Merge request tab positions](img/merge_request_tab_position_v12_6.png) + +Please note this change is currently behind a feature flag which is enabled by default. For +self-managed instances, it can be disabled through the Rails console by a GitLab +administrator with the following command: + +```ruby +Feature.disable(:mr_tabs_position) +``` + ## Creating merge requests While making changes to files in the `master` branch of a repository is possible, it is not diff --git a/doc/user/project/pages/getting_started/fork_sample_project.md b/doc/user/project/pages/getting_started/fork_sample_project.md index ac1a29ca2a0..9c58189e984 100644 --- a/doc/user/project/pages/getting_started/fork_sample_project.md +++ b/doc/user/project/pages/getting_started/fork_sample_project.md @@ -41,7 +41,7 @@ forking (copying) a [sample project from the most popular Static Site Generators and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your site to the server. 1. Once the pipeline has finished successfully, find the link to visit your - website from your project's **Settings > Pages**. It can take aproximatelly + website from your project's **Settings > Pages**. It can take approximately 30 minutes to be deployed. You can also take some **optional** further steps: diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6b6143eba96..405254c6278 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -11212,6 +11212,9 @@ msgstr "" msgid "More information" msgstr "" +msgid "More information and share feedback" +msgstr "" + msgid "More information is available|here" msgstr "" @@ -11823,6 +11826,9 @@ msgstr "" msgid "November" msgstr "" +msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find." +msgstr "" + msgid "Number of Elasticsearch replicas" msgstr "" diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index abf159949db..5b14450a289 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -8,6 +8,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } + let(:enable_mr_tabs_position_flag) { true } let(:config) do { @@ -26,6 +27,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end before do + stub_feature_flags(mr_tabs_position: enable_mr_tabs_position_flag) stub_application_setting(auto_devops_enabled: false) stub_feature_flags(ci_merge_request_pipeline: true) stub_ci_pipeline_yaml_file(YAML.dump(config)) @@ -51,6 +53,7 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d Ci::CreatePipelineService.new(project, user, ref: 'feature') .execute(:merge_request_event, merge_request: merge_request) end + let(:enable_mr_tabs_position_flag) { false } before do visit project_merge_request_path(project, merge_request) @@ -67,9 +70,23 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - it 'sees the latest detached merge request pipeline as the head pipeline', :sidekiq_might_not_need_inline do - page.within('.ci-widget-content') do - expect(page).to have_content("##{detached_merge_request_pipeline.id}") + context 'when merge request tabs feature flag is disabled' do + it 'sees the latest detached merge request pipeline as the head pipeline', :sidekiq_might_not_need_inline do + page.within('.ci-widget-content') do + expect(page).to have_content("##{detached_merge_request_pipeline.id}") + end + end + end + + context 'when merge request tabs feature flag is enabled' do + let(:enable_mr_tabs_position_flag) { true } + + it 'sees the latest detached merge request pipeline as the head pipeline', :sidekiq_might_not_need_inline do + click_link "Overview" + + page.within('.ci-widget-content') do + expect(page).to have_content("##{detached_merge_request_pipeline.id}") + end end end @@ -243,9 +260,23 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end end - it 'sees the latest detached merge request pipeline as the head pipeline' do - page.within('.ci-widget-content') do - expect(page).to have_content("##{detached_merge_request_pipeline.id}") + context 'when merge request tabs feature flag is enabled' do + it 'sees the latest detached merge request pipeline as the head pipeline' do + click_link "Overview" + + page.within('.ci-widget-content') do + expect(page).to have_content("##{detached_merge_request_pipeline.id}") + end + end + end + + context 'when merge request tabs feature flag is disabled' do + let(:enable_mr_tabs_position_flag) { false } + + it 'sees the latest detached merge request pipeline as the head pipeline' do + page.within('.ci-widget-content') do + expect(page).to have_content("##{detached_merge_request_pipeline.id}") + end end end @@ -309,6 +340,8 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d end it 'sees the latest detached merge request pipeline as the head pipeline' do + click_link "Overview" + page.within('.ci-widget-content') do expect(page).to have_content("##{detached_merge_request_pipeline_2.id}") end @@ -323,6 +356,8 @@ describe 'Merge request > User sees pipelines triggered by merge request', :js d context 'when a user merges a merge request from a forked project to the parent project' do before do + click_link("Overview") + click_button 'Merge when pipeline succeeds' wait_for_requests diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb index 3d25611e1ea..e28d2ca5536 100644 --- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb +++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb @@ -25,15 +25,16 @@ describe 'Merge request > User sees MR with deleted source branch', :js do it 'still contains Discussion, Commits and Changes tabs' do within '.merge-request-details' do - expect(page).to have_content('Discussion') + expect(page).to have_content('Overview') expect(page).to have_content('Commits') expect(page).to have_content('Changes') end + expect(page).to have_content('Source branch does not exist.') + click_on 'Changes' wait_for_requests expect(page).to have_selector('.diffs.tab-pane .file-holder') - expect(page).to have_content('Source branch does not exist.') end end diff --git a/vendor/project_templates/hexo.tar.gz b/vendor/project_templates/hexo.tar.gz Binary files differindex 033f363b8df..489da1a34ec 100644 --- a/vendor/project_templates/hexo.tar.gz +++ b/vendor/project_templates/hexo.tar.gz diff --git a/vendor/project_templates/hugo.tar.gz b/vendor/project_templates/hugo.tar.gz Binary files differindex f479ea12900..1f756a696e3 100644 --- a/vendor/project_templates/hugo.tar.gz +++ b/vendor/project_templates/hugo.tar.gz diff --git a/vendor/project_templates/jekyll.tar.gz b/vendor/project_templates/jekyll.tar.gz Binary files differindex c323ce6fac6..0a97723712a 100644 --- a/vendor/project_templates/jekyll.tar.gz +++ b/vendor/project_templates/jekyll.tar.gz |