diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-28 15:08:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-28 15:08:10 +0300 |
commit | a83a97f60432c6c352af80d55339e9fe45b63307 (patch) | |
tree | 40a0ef7fb93580a5ef4b5417c27efab9b2d13b72 | |
parent | 4c788f43cbcd70bcceb4e40891d329952aa016d0 (diff) |
Add latest changes from gitlab-org/gitlab@master
79 files changed, 269 insertions, 1108 deletions
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue index f9dd153eba0..6edbdc7090c 100644 --- a/app/assets/javascripts/badges/components/badge.vue +++ b/app/assets/javascripts/badges/components/badge.vue @@ -84,15 +84,10 @@ export default { <div v-show="hasError" class="btn-group"> <div class="btn btn-default btn-sm disabled"> - <icon - :size="16" - class="prepend-left-8 append-right-8" - name="doc-image" - aria-hidden="true" - /> + <icon :size="16" class="gl-ml-3 append-right-8" name="doc-image" aria-hidden="true" /> </div> <div class="btn btn-default btn-sm disabled"> - <span class="prepend-left-8 append-right-8">{{ s__('Badges|No badge image') }}</span> + <span class="gl-ml-3 append-right-8">{{ s__('Badges|No badge image') }}</span> </div> </div> diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue index 32822a75772..51509cd5fe6 100644 --- a/app/assets/javascripts/ide/components/file_row_extra.vue +++ b/app/assets/javascripts/ide/components/file_row_extra.vue @@ -89,7 +89,7 @@ export default { :type="file.type" :path="file.path" :is-open="dropdownOpen" - class="prepend-left-8" + class="gl-ml-3" v-on="$listeners" /> </div> diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue index 9c0c97bc5ae..f1ba102fffe 100644 --- a/app/assets/javascripts/ide/components/jobs/detail/description.vue +++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue @@ -24,7 +24,7 @@ export default { <template> <div class="d-flex align-items-center"> <ci-icon :status="job.status" :borderless="true" :size="24" class="d-flex" /> - <span class="prepend-left-8"> + <span class="gl-ml-3"> {{ job.name }} <a :href="job.path" target="_blank" class="ide-external-link position-relative"> {{ jobId }} <icon :size="12" name="external-link" /> diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue index 15c312a091b..40dc0a6e80d 100644 --- a/app/assets/javascripts/ide/components/jobs/stage.vue +++ b/app/assets/javascripts/ide/components/jobs/stage.vue @@ -71,7 +71,7 @@ export default { v-tooltip="showTooltip" :title="showTooltip ? stage.name : null" data-container="body" - class="prepend-left-8 text-truncate" + class="gl-ml-3 text-truncate" > {{ stage.name }} </strong> diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue index 4ef2ca98512..6958a5d2526 100644 --- a/app/assets/javascripts/ide/components/pipelines/list.vue +++ b/app/assets/javascripts/ide/components/pipelines/list.vue @@ -63,7 +63,7 @@ export default { <template v-else-if="hasLoadedPipeline"> <header v-if="latestPipeline" class="ide-tree-header ide-pipeline-header"> <ci-icon :status="latestPipeline.details.status" :size="24" class="d-flex" /> - <span class="prepend-left-8"> + <span class="gl-ml-3"> <strong> {{ __('Pipeline') }} </strong> <a :href="latestPipeline.path" diff --git a/app/assets/javascripts/issuable_suggestions/components/item.vue b/app/assets/javascripts/issuable_suggestions/components/item.vue index 76e4fac5107..51904c64085 100644 --- a/app/assets/javascripts/issuable_suggestions/components/item.vue +++ b/app/assets/javascripts/issuable_suggestions/components/item.vue @@ -128,7 +128,7 @@ export default { :key="id" v-gl-tooltip.bottom :title="tooltipTitle" - class="suggestion-help-hover prepend-left-8 text-tertiary" + class="suggestion-help-hover gl-ml-3 text-tertiary" > <icon :name="icon" /> {{ count }} </span> diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/clusters/index.js index 4d04c37caa7..4d04c37caa7 100644 --- a/app/assets/javascripts/pages/groups/index.js +++ b/app/assets/javascripts/pages/groups/clusters/index.js diff --git a/app/assets/javascripts/pages/projects/clusters/index.js b/app/assets/javascripts/pages/projects/clusters/index.js new file mode 100644 index 00000000000..4d04c37caa7 --- /dev/null +++ b/app/assets/javascripts/pages/projects/clusters/index.js @@ -0,0 +1,5 @@ +import initCreateCluster from '~/create_cluster/init_create_cluster'; + +document.addEventListener('DOMContentLoaded', () => { + initCreateCluster(document, gon); +}); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 190d0806c28..8e0af018b61 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,10 +1,7 @@ import Project from './project'; import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation'; -import initCreateCluster from '~/create_cluster/init_create_cluster'; document.addEventListener('DOMContentLoaded', () => { - initCreateCluster(document, gon); - new Project(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new }); diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 1b35f7ac93b..bf474251572 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -405,7 +405,6 @@ img.emoji { .prepend-top-20 { margin-top: 20px; } .prepend-top-32 { margin-top: 32px; } .prepend-left-5 { margin-left: 5px; } -.prepend-left-8 { margin-left: 8px; } .prepend-left-10 { margin-left: 10px; } .prepend-left-15 { margin-left: 15px; } .prepend-left-default { margin-left: $gl-padding; } diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss index 10f0a6aa089..2b82b2226c6 100644 --- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss +++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss @@ -221,7 +221,7 @@ } @function calc-btn-hover-padding($original-padding, $original-border: 1px) { - @return calc(#{$original-padding + $original-border} - var(--ide-btn-hover-border-width, $original-border)); + @return calc(#{$original-padding + $original-border} - var(--ide-btn-hover-border-width, #{$original-border})); } .btn:not(.btn-link):not([disabled]):hover { diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index dbc575a1487..29138e7b014 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -51,13 +51,7 @@ module MilestoneActions } end - # rubocop:disable Gitlab/ModuleWithInstanceVariables def milestone_redirect_path - if @milestone.global_milestone? - url_for(action: :show, title: @milestone.title) - else - url_for(action: :show) - end + url_for(action: :show) end - # rubocop:enable Gitlab/ModuleWithInstanceVariables end diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index d34a07324da..14f9a026688 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,48 +1,32 @@ # frozen_string_literal: true class Dashboard::MilestonesController < Dashboard::ApplicationController - include MilestoneActions - before_action :projects before_action :groups, only: :index - before_action :milestone, only: [:show, :merge_requests, :participants, :labels] def index respond_to do |format| format.html do - @milestone_states = Milestone.states_count(@projects.select(:id), @groups.select(:id)) - @milestones = Kaminari.paginate_array(milestones).page(params[:page]) + @milestone_states = Milestone.states_count(@projects.select(:id), groups.select(:id)) + @milestones = milestones.page(params[:page]) end format.json do - render json: milestones + render json: milestones.to_json(only: [:id, :title], methods: :name) end end end - def show - end - private - def group_milestones - DashboardGroupMilestone.build_collection(groups, params) - end - - # See [#39545](https://gitlab.com/gitlab-org/gitlab-foss/issues/39545) for info about the deprecation of dynamic milestones - def dynamic_milestones - DashboardMilestone.build_collection(@projects, params) - end - def milestones - @milestones = group_milestones + dynamic_milestones - end - - def milestone - @milestone = DashboardMilestone.build(@projects, params[:title]) - render_404 unless @milestone + MilestonesFinder.new(search_params).execute end def groups @groups ||= GroupsFinder.new(current_user, all_available: false).execute end + + def search_params + params.permit(:state, :search_title).merge(group_ids: groups, project_ids: projects) + end end diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 8cfbd293597..c9fe6bddb50 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -6,17 +6,17 @@ class Groups::MilestonesController < Groups::ApplicationController before_action :milestone, only: [:edit, :show, :update, :merge_requests, :participants, :labels, :destroy] before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy] before_action do - push_frontend_feature_flag(:burnup_charts) + push_frontend_feature_flag(:burnup_charts, @group) end def index respond_to do |format| format.html do @milestone_states = Milestone.states_count(group_projects_with_access, [group]) - @milestones = Kaminari.paginate_array(milestones).page(params[:page]) + @milestones = milestones.page(params[:page]) end format.json do - render json: milestones.map { |m| m.for_display.slice(:id, :title, :name) } + render json: milestones.to_json(only: [:id, :title], methods: :name) end end end @@ -29,7 +29,7 @@ class Groups::MilestonesController < Groups::ApplicationController @milestone = Milestones::CreateService.new(group, current_user, milestone_params).execute if @milestone.persisted? - redirect_to milestone_path + redirect_to milestone_path(@milestone) else render "new" end @@ -39,23 +39,15 @@ class Groups::MilestonesController < Groups::ApplicationController end def edit - render_404 if @milestone.legacy_group_milestone? end def update - # Keep this compatible with legacy group milestones where we have to update - # all projects milestones states at once. - milestones, update_params = get_milestones_for_update - milestones.each do |milestone| - Milestones::UpdateService.new(milestone.resource_parent, current_user, update_params).execute(milestone) - end + Milestones::UpdateService.new(@milestone.parent, current_user, milestone_params).execute(@milestone) - redirect_to milestone_path + redirect_to milestone_path(@milestone) end def destroy - return render_404 if @milestone.legacy_group_milestone? - Milestones::DestroyService.new(group, current_user).execute(@milestone) respond_to do |format| @@ -66,14 +58,6 @@ class Groups::MilestonesController < Groups::ApplicationController private - def get_milestones_for_update - if @milestone.legacy_group_milestone? - [@milestone.milestones, legacy_milestone_params] - else - [[@milestone], milestone_params] - end - end - def authorize_admin_milestones! return render_404 unless can?(current_user, :admin_milestone, group) end @@ -82,27 +66,21 @@ class Groups::MilestonesController < Groups::ApplicationController params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) end - def legacy_milestone_params - params.require(:milestone).permit(:state_event) + def milestones + MilestonesFinder.new(search_params).execute end - def milestone_path - if @milestone.legacy_group_milestone? - group_milestone_path(group, @milestone.safe_title, title: @milestone.title) - else - group_milestone_path(group, @milestone.iid) - end + def milestone + @milestone = group.milestones.find_by_iid(params[:id]) + + render_404 unless @milestone end - def milestones - milestones = MilestonesFinder.new(search_params).execute + def search_params + groups = request.format.json? ? group_ids(include_ancestors: true) : group_ids @sort = params[:sort] || 'due_date_asc' - MilestoneArray.sort(milestones + legacy_milestones, @sort) - end - - def legacy_milestones - GroupMilestone.build_collection(group, group_projects_with_access, params) + params.permit(:state, :search_title).merge(sort: @sort, group_ids: groups, project_ids: group_projects_with_access) end def group_projects_with_access @@ -116,23 +94,6 @@ class Groups::MilestonesController < Groups::ApplicationController group.self_and_descendants.public_or_visible_to_user(current_user).select(:id) end end - - def milestone - @milestone = - if params[:title] - GroupMilestone.build(group, group_projects_with_access, params[:title]) - else - group.milestones.find_by_iid(params[:id]) - end - - render_404 unless @milestone - end - - def search_params - groups = request.format.json? ? group_ids(include_ancestors: true) : group_ids - - params.permit(:state, :search_title).merge(group_ids: groups) - end end Groups::MilestonesController.prepend_if_ee('EE::Groups::MilestonesController') diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 56f1f1a1019..16d63cc184f 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -7,7 +7,7 @@ class Projects::MilestonesController < Projects::ApplicationController before_action :check_issuables_available! before_action :milestone, only: [:edit, :update, :destroy, :show, :merge_requests, :participants, :labels, :promote] before_action do - push_frontend_feature_flag(:burnup_charts) + push_frontend_feature_flag(:burnup_charts, @project) end # Allow read any milestone @@ -34,7 +34,7 @@ class Projects::MilestonesController < Projects::ApplicationController @milestones = @milestones.page(params[:page]) end format.json do - render json: @milestones.to_json(methods: :name) + render json: @milestones.to_json(only: [:id, :title], methods: :name) end end end diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb index cfe648d9f79..8f0cdf3b255 100644 --- a/app/finders/milestones_finder.rb +++ b/app/finders/milestones_finder.rb @@ -58,10 +58,8 @@ class MilestonesFinder Milestone.filter_by_state(items, params[:state]) end - # rubocop: disable CodeReuse/ActiveRecord def order(items) - order_statement = Gitlab::Database.nulls_last_order('due_date', 'ASC') - items.reorder(order_statement).order('title ASC') + sort_by = params[:sort].presence || 'due_date_asc' + items.sort_by_attribute(sort_by) end - # rubocop: enable CodeReuse/ActiveRecord end diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 884ee64b6f5..9534ab19c39 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -207,7 +207,7 @@ module IssuablesHelper output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) - output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block prepend-left-8") + output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block gl-ml-3") output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none") output.join.html_safe diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb index 87ea22d8f83..0bffdba7349 100644 --- a/app/helpers/timeboxes_helper.rb +++ b/app/helpers/timeboxes_helper.rb @@ -229,11 +229,7 @@ module TimeboxesHelper alias_method :milestone_date_range, :timebox_date_range def milestone_tab_path(milestone, tab) - if milestone.global_milestone? - url_for(action: tab, title: milestone.title, format: :json) - else - url_for(action: tab, format: :json) - end + url_for(action: tab, format: :json) end def update_milestone_path(milestone, params = {}) @@ -247,11 +243,7 @@ module TimeboxesHelper def group_milestone_route(milestone, params = {}) params = nil if params.empty? - if milestone.legacy_group_milestone? - group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: params) - else - group_milestone_path(milestone.group, milestone.iid, milestone: params) - end + group_milestone_path(milestone.group, milestone.iid, milestone: params) end def group_or_project_milestone_path(milestone) diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index fa5a79cc12b..5f24564dc56 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -97,26 +97,6 @@ module Milestoneish due_date && due_date.past? end - def group_milestone? - false - end - - def project_milestone? - false - end - - def legacy_group_milestone? - false - end - - def dashboard_milestone? - false - end - - def global_milestone? - false - end - def total_time_spent @total_time_spent ||= issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent) end diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb deleted file mode 100644 index 48c09f4cd6b..00000000000 --- a/app/models/dashboard_group_milestone.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true -# Dashboard Group Milestones are milestones that allow us to pull more info out for the UI that the Milestone object doesn't allow for -class DashboardGroupMilestone < GlobalMilestone - extend ::Gitlab::Utils::Override - - attr_reader :group_name - - def initialize(milestone) - super - - @group_name = milestone.group.full_name - end - - def self.build_collection(groups, params) - milestones = Milestone.of_groups(groups.select(:id)) - .reorder_by_due_date_asc - .order_by_name_asc - milestones = milestones.search_title(params[:search_title]) if params[:search_title].present? - Milestone.filter_by_state(milestones, params[:state]).map { |m| new(m) } - end - - def dashboard_milestone? - true - end - - def merge_requests_enabled? - true - end -end diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb deleted file mode 100644 index fd59b94b737..00000000000 --- a/app/models/dashboard_milestone.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -class DashboardMilestone < GlobalMilestone - attr_reader :project_name - - def initialize(milestone) - super - - @project_name = milestone.project.full_name - end - - def project_milestone? - true - end - - def merge_requests_enabled? - project.merge_requests_enabled? - end -end diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb deleted file mode 100644 index 43de7454cb7..00000000000 --- a/app/models/global_milestone.rb +++ /dev/null @@ -1,108 +0,0 @@ -# frozen_string_literal: true -# Global Milestones are milestones that can be shared across multiple projects -class GlobalMilestone - include Milestoneish - - STATE_COUNT_HASH = { opened: 0, closed: 0, all: 0 }.freeze - - attr_reader :milestone - alias_attribute :name, :title - - delegate :title, :state, :due_date, :start_date, :participants, :project, - :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, - :timebox_id, :milestoneish_id, :resource_parent, :releases, to: :milestone - - def to_hash - { - name: title, - title: title, - group_name: group&.full_name, - project_name: project&.full_name - } - end - - def for_display - @milestone - end - - def self.build_collection(projects, params) - items = Milestone.of_projects(projects) - .reorder_by_due_date_asc - .order_by_name_asc - items = items.search_title(params[:search_title]) if params[:search_title].present? - - Milestone.filter_by_state(items, params[:state]).map { |m| new(m) } - end - - # necessary for legacy milestones - def self.build(projects, title) - milestones = Milestone.of_projects(projects).where(title: title) - return if milestones.blank? - - new(milestones.first) - end - - def self.states_count(projects, group = nil) - legacy_group_milestones_count = legacy_group_milestone_states_count(projects) - group_milestones_count = group_milestones_states_count(group) - - legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count| - legacy_group_milestones_count + group_milestones_count - end - end - - def self.group_milestones_states_count(group) - return STATE_COUNT_HASH unless group - - counts_by_state = Milestone.of_groups(group).count_by_state - - { - opened: counts_by_state['active'] || 0, - closed: counts_by_state['closed'] || 0, - all: counts_by_state.values.sum - } - end - - def self.legacy_group_milestone_states_count(projects) - return STATE_COUNT_HASH unless projects - - # We need to reorder(nil) on the projects, because the controller passes them in sorted. - relation = Milestone.of_projects(projects.reorder(nil)).count_by_state - - { - opened: relation['active'] || 0, - closed: relation['closed'] || 0, - all: relation.values.sum - } - end - - def initialize(milestone) - @milestone = milestone - end - - def active? - state == 'active' - end - - def closed? - state == 'closed' - end - - def issues - @issues ||= Issue.of_milestones(milestone).includes(:project, :assignees, :labels) - end - - def merge_requests - @merge_requests ||= MergeRequest.of_milestones(milestone).includes(:target_project, :assignees, :labels) - end - - def labels - @labels ||= GlobalLabel.build_collection(milestone.labels).sort_by!(&:title) - end - - def global_milestone? - true - end -end - -GlobalMilestone.include_if_ee('::EE::GlobalMilestone') diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb deleted file mode 100644 index 60e97174e50..00000000000 --- a/app/models/group_milestone.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true -# Group Milestones are milestones that can be shared among many projects within the same group -class GroupMilestone < GlobalMilestone - attr_reader :group, :milestones - - def self.build_collection(group, projects, params) - params = - { state: params[:state], search_title: params[:search_title] } - - project_milestones = Milestone.of_projects(projects) - project_milestones = project_milestones.search_title(params[:search_title]) if params[:search_title].present? - child_milestones = Milestone.filter_by_state(project_milestones, params[:state]) - grouped_milestones = child_milestones.group_by(&:title) - - grouped_milestones.map do |title, grouped| - new(title, grouped, group) - end - end - - def self.build(group, projects, title) - child_milestones = Milestone.of_projects(projects).where(title: title) - return if child_milestones.blank? - - new(title, child_milestones, group) - end - - def initialize(title, milestones, group) - @milestones = milestones - @group = group - end - - def milestone - @milestone ||= milestones.find { |m| m.description.present? } || milestones.first - end - - def issues_finder_params - { group_id: group.id } - end - - def legacy_group_milestone? - true - end - - def merge_requests_enabled? - true - end -end - -GroupMilestone.include_if_ee('::EE::GroupMilestone') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 3c795ebd1d6..3409c249826 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1313,8 +1313,6 @@ class MergeRequest < ApplicationRecord end def has_accessibility_reports? - return false unless Feature.enabled?(:accessibility_report_view, project) - actual_head_pipeline.present? && actual_head_pipeline.has_reports?(Ci::JobArtifact.accessibility_reports) end diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml index 89212eb6bf9..4921de32f65 100644 --- a/app/views/dashboard/milestones/_milestone.html.haml +++ b/app/views/dashboard/milestones/_milestone.html.haml @@ -1,5 +1,4 @@ = render 'shared/milestones/milestone', - milestone_path: group_or_project_milestone_path(milestone), issues_path: issues_dashboard_path(milestone_title: milestone.title), merge_requests_path: merge_requests_dashboard_path(milestone_title: milestone.title), milestone: milestone, diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml deleted file mode 100644 index 2129920afd2..00000000000 --- a/app/views/dashboard/milestones/show.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -- header_title "Milestones", dashboard_milestones_path - -= render 'shared/milestones/top', milestone: @milestone -= render 'shared/milestones/tabs', milestone: @milestone, show_full_project_name: true -= render 'shared/milestones/sidebar', milestone: @milestone, affix_offset: 51 diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml index 70dd0420f6b..9bf7ad228d9 100644 --- a/app/views/groups/_home_panel.html.haml +++ b/app/views/groups/_home_panel.html.haml @@ -17,7 +17,7 @@ %span = _("Group ID: %{group_id}") % { group_id: @group.id } - if current_user - %span.access-request-links.prepend-left-8 + %span.access-request-links.gl-ml-3 = render 'shared/members/access_request_links', source: @group .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml index bae8997e24c..b73626dab81 100644 --- a/app/views/groups/milestones/_milestone.html.haml +++ b/app/views/groups/milestones/_milestone.html.haml @@ -1,6 +1,4 @@ - = render 'shared/milestones/milestone', - milestone_path: group_milestone_route(milestone), issues_path: issues_group_path(@group, milestone_title: milestone.title), merge_requests_path: merge_requests_group_path(@group, milestone_title: milestone.title), milestone: milestone diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b6fb908c8f6..03407adb57d 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -16,5 +16,8 @@ .nothing-here-block No milestones to show - else - @milestones.each do |milestone| - = render 'milestone', milestone: milestone + - if milestone.project_milestone? + = render 'projects/milestones/milestone', milestone: milestone + - else + = render 'milestone', milestone: milestone = paginate @milestones, theme: "gitlab" diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 99c4fc0d1b6..5974b8d7c6a 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -18,7 +18,7 @@ - if ActionController::Base.asset_host %link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host } - %link{ rel: 'preconnnect', href: ActionController::Base.asset_host, crossorigin: '' } + %link{ rel: 'preconnect', href: ActionController::Base.asset_host, crossorigin: '' } %meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' } diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index f6255dac7cf..c82fa1021fc 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -16,7 +16,7 @@ = brand_header_logo - logo_text = brand_header_logo_type - if logo_text.present? - %span.logo-text.d-none.d-lg-block.prepend-left-8 + %span.logo-text.d-none.d-lg-block.gl-ml-3 = logo_text - if Gitlab.com_and_canary? = link_to 'https://next.gitlab.com', class: 'label-link canary-badge bg-transparent', target: :_blank do diff --git a/app/views/layouts/header/_logo_with_title.html.haml b/app/views/layouts/header/_logo_with_title.html.haml index 1ea6168fc9a..9b5a47306d2 100644 --- a/app/views/layouts/header/_logo_with_title.html.haml +++ b/app/views/layouts/header/_logo_with_title.html.haml @@ -1,4 +1,4 @@ %header.navbar.fixed-top.navbar-gitlab.justify-content-center = render 'shared/logo.svg' - %span.logo-text.d-none.d-lg-block.prepend-left-8.pt-1 + %span.logo-text.d-none.d-lg-block.gl-ml-3.pt-1 = render 'shared/logo_type.svg' diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml index f9ca77e994d..e39cb5ee0a2 100644 --- a/app/views/layouts/terms.html.haml +++ b/app/views/layouts/terms.html.haml @@ -19,7 +19,7 @@ = brand_header_logo - logo_text = brand_header_logo_type - if logo_text.present? - %span.logo-text.prepend-left-8 + %span.logo-text.gl-ml-3 = logo_text - if header_link?(:user_dropdown) .navbar-collapse diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml index 0fe54e73313..341aa6f8103 100644 --- a/app/views/notify/merged_merge_request_email.html.haml +++ b/app/views/notify/merged_merge_request_email.html.haml @@ -1,2 +1,2 @@ %p - Merge Request #{@merge_request.to_reference} was merged + Merge Request #{link_to @merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request)} was merged diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml index d623e701a30..74e6f86f603 100644 --- a/app/views/notify/merged_merge_request_email.text.haml +++ b/app/views/notify/merged_merge_request_email.text.haml @@ -1,6 +1,6 @@ Merge Request #{@merge_request.to_reference} was merged -Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} +Merge Request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)} = merge_path_description(@merge_request, 'to') diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 9d866d9f81b..b4e218451a0 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -20,7 +20,7 @@ %span.text-secondary = s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id } - if current_user - %span.access-request-links.prepend-left-8 + %span.access-request-links.gl-ml-3 = render 'shared/members/access_request_links', source: @project - if @project.tag_list.present? %span.home-panel-topic-list.mt-2.w-100.d-inline-flex diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 3e53cb510b0..26053a25a3e 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -5,7 +5,7 @@ .branch-info .branch-title = sprite_icon('fork', size: 12) - = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8 qa-branch-name' do + = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3 qa-branch-name' do = branch.name - if branch.name == @repository.root_ref %span.badge.badge-primary.prepend-left-5 default diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index d030b2c07a5..d5249662dde 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -39,7 +39,7 @@ .d-flex %h3.page-title= @environment.name - if @environment.auto_stop_at? - %p.align-self-end.prepend-left-8 + %p.align-self-end.gl-ml-3 = s_('Environments|Auto stops %{auto_stop_time}').html_safe % {auto_stop_time: time_ago_with_tooltip(@environment.auto_stop_at)} .nav-controls.my-2 = render 'projects/environments/pin_button', environment: @environment diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml index f3a1edd2571..a77eea8beaa 100644 --- a/app/views/projects/issues/_new_branch.html.haml +++ b/app/views/projects/issues/_new_branch.html.haml @@ -41,7 +41,7 @@ = _('Create branch') %li.divider.droplab-item-ignore - %li.droplab-item-ignore.prepend-left-8.append-right-8.prepend-top-16 + %li.droplab-item-ignore.gl-ml-3.append-right-8.prepend-top-16 - if can_create_confidential_merge_request? #js-forked-project{ data: { namespace_path: @project.namespace.full_path, project_path: @project.full_path, new_fork_path: new_project_fork_path(@project), help_page_path: help_page_path('user/project/merge_requests') } } .form-group diff --git a/app/views/projects/milestones/_milestone.html.haml b/app/views/projects/milestones/_milestone.html.haml index bc82b45f902..00937c5bf73 100644 --- a/app/views/projects/milestones/_milestone.html.haml +++ b/app/views/projects/milestones/_milestone.html.haml @@ -1,5 +1,4 @@ = render 'shared/milestones/milestone', - milestone_path: project_milestone_path(milestone.project, milestone), issues_path: project_issues_path(milestone.project, milestone_title: milestone.title), merge_requests_path: project_merge_requests_path(milestone.project, milestone_title: milestone.title), milestone: milestone diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml index 2da857261d1..99a46f1fb85 100644 --- a/app/views/shared/milestones/_header.html.haml +++ b/app/views/shared/milestones/_header.html.haml @@ -11,8 +11,7 @@ .milestone-buttons - if can?(current_user, :admin_milestone, @group || @project) - - unless milestone.legacy_group_milestone? - = link_to _('Edit'), edit_milestone_path(milestone), class: 'btn btn-grouped' + = link_to _('Edit'), edit_milestone_path(milestone), class: 'btn btn-grouped' - if milestone.project_milestone? && milestone.project.group %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal', @@ -31,8 +30,7 @@ - else = link_to _('Reopen milestone'), update_milestone_path(milestone, { state_event: :activate }), method: :put, class: 'btn btn-grouped btn-reopen' - - unless milestone.legacy_group_milestone? - = render 'shared/milestones/delete_button' + = render 'shared/milestones/delete_button' %button.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ type: 'button' } = icon('angle-double-left') diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml index 9f61082d605..a951c0a5119 100644 --- a/app/views/shared/milestones/_milestone.html.haml +++ b/app/views/shared/milestones/_milestone.html.haml @@ -6,39 +6,33 @@ .row .col-sm-6 .append-bottom-5 - %strong= link_to truncate(milestone.title, length: 100), milestone_path + %strong= link_to truncate(milestone.title, length: 100), milestone_path(milestone) - if @group = " - #{milestone_type}" - - if @project || milestone.is_a?(GlobalMilestone) || milestone.group_milestone? - - if milestone.due_date || milestone.start_date - .text-tertiary.append-bottom-5 - = milestone_date_range(milestone) - - recent_releases, total_count, more_count = recent_releases_with_counts(milestone) - - unless total_count.zero? - .text-tertiary.append-bottom-5.milestone-release-links - = icon('rocket') - = n_('Release', 'Releases', total_count) - - recent_releases.each do |release| - = link_to release.name, project_releases_path(release.project, anchor: release.tag) - - unless release == recent_releases.last - • - - if total_count > recent_releases.count + - if milestone.due_date || milestone.start_date + .text-tertiary.append-bottom-5 + = milestone_date_range(milestone) + - recent_releases, total_count, more_count = recent_releases_with_counts(milestone) + - unless total_count.zero? + .text-tertiary.append-bottom-5.milestone-release-links + = icon('rocket') + = n_('Release', 'Releases', total_count) + - recent_releases.each do |release| + = link_to release.name, project_releases_path(release.project, anchor: release.tag) + - unless release == recent_releases.last • - = link_to n_('%{count} more release', '%{count} more releases', more_count) % { count: more_count }, project_releases_path(milestone.project) - %div - = render('shared/milestone_expired', milestone: milestone) - - if milestone.group_milestone? - .label-badge.label-badge-blue.d-inline-block - = milestone.group.full_name - - if milestone.legacy_group_milestone? - .projects - - link_to milestone_path(milestone.milestone) do - %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5 - = dashboard ? milestone.project.full_name : milestone.project.name - - if milestone.project - .label-badge.label-badge-gray.d-inline-block - = milestone.project.full_name + - if total_count > recent_releases.count + • + = link_to n_('%{count} more release', '%{count} more releases', more_count) % { count: more_count }, project_releases_path(milestone.project) + %div + = render('shared/milestone_expired', milestone: milestone) + - if milestone.group_milestone? + .label-badge.label-badge-blue.d-inline-block + = milestone.group.full_name + - if milestone.project_milestone? + .label-badge.label-badge-gray.d-inline-block + = milestone.project.full_name .col-sm-4.milestone-progress = milestone_progress_bar(milestone) @@ -49,29 +43,25 @@ .float-lg-right.light #{milestone.percent_complete}% complete .col-sm-2 .milestone-actions.d-flex.justify-content-sm-start.justify-content-md-end - - if @project - - if can_admin_project_milestones? and milestone.active? - - if can_admin_group_milestones? - %button.js-promote-project-milestone-button.btn.btn-blank.btn-sm.btn-grouped.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'), - disabled: true, - type: 'button', - data: { url: promote_project_milestone_path(milestone.project, milestone), - milestone_title: milestone.title, - group_name: @project.group.name, - target: '#promote-milestone-modal', - container: 'body', - toggle: 'modal' } } - = sprite_icon('level-up', size: 14) + - if @project # if in milestones list on project level + - if can_admin_group_milestones? + %button.js-promote-project-milestone-button.btn.btn-blank.btn-sm.btn-grouped.has-tooltip{ title: s_('Milestones|Promote to Group Milestone'), + disabled: true, + type: 'button', + data: { url: promote_project_milestone_path(milestone.project, milestone), + milestone_title: milestone.title, + group_name: @project.group.name, + target: '#promote-milestone-modal', + container: 'body', + toggle: 'modal' } } + = sprite_icon('level-up', size: 14) + + - if can?(current_user, :admin_milestone, milestone) + - if milestone.closed? + = link_to s_('Milestones|Reopen Milestone'), milestone_path(milestone, milestone: { state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" + - else + = link_to s_('Milestones|Close Milestone'), milestone_path(milestone, milestone: { state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close" - = link_to s_('Milestones|Close Milestone'), project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close btn-grouped" - - unless milestone.active? - = link_to s_('Milestones|Reopen Milestone'), project_milestone_path(@project, milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen" - - if @group - - if can?(current_user, :admin_milestone, @group) - - if milestone.closed? - = link_to s_('Milestones|Reopen Milestone'), group_milestone_route(milestone, {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" - - else - = link_to s_('Milestones|Close Milestone'), group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close" - if dashboard .label-badge.label-badge-gray = milestone_type diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml index 5f53e6316af..49df00940b7 100644 --- a/app/views/shared/milestones/_top.html.haml +++ b/app/views/shared/milestones/_top.html.haml @@ -1,11 +1,9 @@ - page_title milestone.title -- @breadcrumb_link = dashboard_milestone_path(milestone.safe_title, title: milestone.title) +- @breadcrumb_link = milestone_path(milestone) - group = local_assigns[:group] -- is_dynamic_milestone = milestone.legacy_group_milestone? || milestone.dashboard_milestone? = render 'shared/milestones/header', milestone: milestone -= render 'shared/milestones/deprecation_message' if is_dynamic_milestone = render 'shared/milestones/description', milestone: milestone - if milestone.complete? && milestone.active? @@ -15,26 +13,3 @@ = group ? _('You may close the milestone now.') : _('Navigate to the project to close the milestone.') = render_if_exists 'shared/milestones/burndown', milestone: milestone, project: @project - -- if is_dynamic_milestone - .table-holder - %table.table - %thead - %tr - %th= _('Project') - %th= _('Open issues') - %th= _('State') - %th= _('Due date') - %tr - %td - - project_name = group ? milestone.project.name : milestone.project.full_name - = link_to project_name, milestone_path(milestone.milestone) - %td - = milestone.milestone.issues_visible_to_user(current_user).opened.count - %td - - if milestone.closed? - = _('Closed') - - else - = _('Open') - %td - = milestone.expires_at diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml index 4fa04402a1c..bc4861d6ae8 100644 --- a/app/views/users/terms/index.html.haml +++ b/app/views/users/terms/index.html.haml @@ -6,13 +6,13 @@ .card-footer.footer-block.clearfix - if can?(current_user, :accept_terms, @term) .float-right - = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success prepend-left-8', data: { qa_selector: 'accept_terms_button' } do + = button_to accept_term_path(@term, redirect_params), class: 'btn btn-success gl-ml-3', data: { qa_selector: 'accept_terms_button' } do = _('Accept terms') - else .pull-right - = link_to root_path, class: 'btn btn-success prepend-left-8' do + = link_to root_path, class: 'btn btn-success gl-ml-3' do = _('Continue') - if can?(current_user, :decline_terms, @term) .float-right - = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default prepend-left-8' do + = button_to decline_term_path(@term, redirect_params), class: 'btn btn-default gl-ml-3' do = _('Decline and sign out') diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb index 7622f40a949..09f53681e7f 100644 --- a/app/workers/irker_worker.rb +++ b/app/workers/irker_worker.rb @@ -70,7 +70,7 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker def send_new_branch(project, repo_name, committer, branch) repo_path = project.full_path - newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/branches" + newbranch = "#{Gitlab.config.gitlab.url}/#{repo_path}/-/branches" newbranch = "\x0302\x1f#{newbranch}\x0f" if @colors privmsg = "[#{repo_name}] #{committer} has created a new branch " \ @@ -124,7 +124,7 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker def compare_url(data, repo_path) sha1 = Commit.truncate_sha(data['before']) sha2 = Commit.truncate_sha(data['after']) - compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/compare" \ + compare_url = "#{Gitlab.config.gitlab.url}/#{repo_path}/-/compare" \ "/#{sha1}...#{sha2}" colorize_url compare_url end diff --git a/changelogs/unreleased/218414-refine-sast-analyzer-language-detection.yml b/changelogs/unreleased/218414-refine-sast-analyzer-language-detection.yml new file mode 100644 index 00000000000..b385ee3a25c --- /dev/null +++ b/changelogs/unreleased/218414-refine-sast-analyzer-language-detection.yml @@ -0,0 +1,5 @@ +--- +title: Refine SAST language detection by frameworks +merge_request: 33226 +author: +type: changed diff --git a/changelogs/unreleased/39545-cleanup-dynamic-milestone-pages.yml b/changelogs/unreleased/39545-cleanup-dynamic-milestone-pages.yml new file mode 100644 index 00000000000..e2ab210a333 --- /dev/null +++ b/changelogs/unreleased/39545-cleanup-dynamic-milestone-pages.yml @@ -0,0 +1,5 @@ +--- +title: Remove deprecated dashboard & group milestone pages +merge_request: 13237 +author: +type: removed diff --git a/changelogs/unreleased/cablett-merge-request-merged-email-ref.yml b/changelogs/unreleased/cablett-merge-request-merged-email-ref.yml new file mode 100644 index 00000000000..4d2128c5910 --- /dev/null +++ b/changelogs/unreleased/cablett-merge-request-merged-email-ref.yml @@ -0,0 +1,5 @@ +--- +title: Render Merge request reference as link +merge_request: 33248 +author: +type: changed diff --git a/changelogs/unreleased/fix_preconnect_typo.yml b/changelogs/unreleased/fix_preconnect_typo.yml new file mode 100644 index 00000000000..433bab8ec9d --- /dev/null +++ b/changelogs/unreleased/fix_preconnect_typo.yml @@ -0,0 +1,5 @@ +--- +title: Fix preconnect typo in rel link +merge_request: 33255 +author: +type: performance diff --git a/changelogs/unreleased/patch-127.yml b/changelogs/unreleased/patch-127.yml new file mode 100644 index 00000000000..57d48ac347d --- /dev/null +++ b/changelogs/unreleased/patch-127.yml @@ -0,0 +1,5 @@ +--- +title: Update deprecated routes in irker integration +merge_request: 32923 +author: Marc Jeanmougin +type: fixed diff --git a/changelogs/unreleased/remove-a11y-widget-ff.yml b/changelogs/unreleased/remove-a11y-widget-ff.yml new file mode 100644 index 00000000000..0f99d7a1e93 --- /dev/null +++ b/changelogs/unreleased/remove-a11y-widget-ff.yml @@ -0,0 +1,5 @@ +--- +title: Add accessibility report MR widget +merge_request: 32902 +author: +type: added diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb index f1e8c2b9d82..7e29a36f020 100644 --- a/config/routes/dashboard.rb +++ b/config/routes/dashboard.rb @@ -5,13 +5,7 @@ resource :dashboard, controller: 'dashboard', only: [] do get :activity scope module: :dashboard do - resources :milestones, only: [:index, :show] do - member do - get :merge_requests - get :participants - get :labels - end - end + resources :milestones, only: [:index] resources :labels, only: [:index] resources :groups, only: [:index] diff --git a/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb b/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb new file mode 100644 index 00000000000..e9a9dd5eff8 --- /dev/null +++ b/db/post_migrate/20200527094322_drop_vulnerability_confidence_index.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class DropVulnerabilityConfidenceIndex < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + DOWNTIME = false + INDEX_NAME = 'index_vulnerability_on_id_and_confidence_eq_zero' + + def up + Gitlab::BackgroundMigration.steal('RemoveUndefinedVulnerabilityConfidenceLevel') + + remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME + end + + def down + add_concurrent_index(:vulnerabilities, :id, where: 'confidence = 0', name: INDEX_NAME) + end +end diff --git a/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb b/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb new file mode 100644 index 00000000000..99fe4da7686 --- /dev/null +++ b/db/post_migrate/20200527095401_drop_vulnerability_occurrence_confidence_index.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class DropVulnerabilityOccurrenceConfidenceIndex < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + DOWNTIME = false + INDEX_NAME = 'index_vulnerability_occurrences_on_id_and_confidence_eq_zero' + + def up + Gitlab::BackgroundMigration.steal('RemoveUndefinedOccurrenceConfidenceLevel') + + remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME + end + + def down + add_concurrent_index(:vulnerability_occurrences, :id, where: 'confidence = 0', name: INDEX_NAME) + end +end diff --git a/db/structure.sql b/db/structure.sql index f5ea66618d2..0f5065719da 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -10932,8 +10932,6 @@ CREATE UNIQUE INDEX index_vulnerability_occurrence_identifiers_on_unique_keys ON CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON public.vulnerability_occurrence_pipelines USING btree (pipeline_id); -CREATE INDEX index_vulnerability_occurrences_on_id_and_confidence_eq_zero ON public.vulnerability_occurrences USING btree (id) WHERE (confidence = 0); - CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON public.vulnerability_occurrences USING btree (primary_identifier_id); CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON public.vulnerability_occurrences USING btree (scanner_id); @@ -10944,8 +10942,6 @@ CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON public.vulnerabil CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON public.vulnerability_occurrences USING btree (vulnerability_id); -CREATE INDEX index_vulnerability_on_id_and_confidence_eq_zero ON public.vulnerabilities USING btree (id) WHERE (confidence = 0); - CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON public.vulnerability_scanners USING btree (project_id, external_id); CREATE UNIQUE INDEX index_vulnerability_user_mentions_on_note_id ON public.vulnerability_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL); @@ -13958,5 +13954,7 @@ COPY "schema_migrations" (version) FROM STDIN; 20200526120714 20200526164946 20200526164947 +20200527094322 +20200527095401 \. diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md index 9095935e6dc..8a27f5f7a4e 100644 --- a/doc/administration/geo/disaster_recovery/index.md +++ b/doc/administration/geo/disaster_recovery/index.md @@ -184,6 +184,27 @@ required: set the database to read-write: - Amazon RDS - [Promoting a Read Replica to Be a Standalone DB Instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Promote) - Azure Database for PostgreSQL - [Stop replication](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal#stop-replication) + - Other external PostgreSQL databases - save the script below in you secondary node, for example + `/tmp/geo_promote.sh`, and modify the connection parameters to match your + environment. Then, execute it to promote the replica: + + ```shell + #!/bin/bash + + PG_SUPERUSER=postgres + + # The path to your pg_ctl binary. You may need to adjust this path to match + # your PostgreSQL installation + PG_CTL_BINARY=/usr/lib/postgresql/10/bin/pg_ctl + + # The path to your PostgreSQL data directory. You may need to adjust this + # path to match your PostgreSQL installation. You can also run + # `SHOW data_directory;` from PostgreSQL to find your data directory + PG_DATA_DIRECTORY=/etc/postgresql/10/main + + # Promote the PostgreSQL database and allow read/write operations + sudo -u $PG_SUPERUSER $PG_CTL_BINARY -D $PG_DATA_DIRECTORY promote + ``` 1. Edit `/etc/gitlab/gitlab.rb` on every node in the **secondary** site to reflect its new status as **primary** by removing any lines that enabled the diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md index 18b9161e3b9..a16e2157e30 100644 --- a/doc/administration/high_availability/load_balancer.md +++ b/doc/administration/high_availability/load_balancer.md @@ -2,9 +2,9 @@ type: reference --- -# Load Balancer for GitLab HA +# Load Balancer for multi-node GitLab -In an active/active GitLab configuration, you will need a load balancer to route +In an multi-node GitLab configuration, you will need a load balancer to route traffic to the application servers. The specifics on which load balancer to use or the exact configuration is beyond the scope of GitLab documentation. We hope that if you're managing HA systems like GitLab you have a load balancer of @@ -14,7 +14,7 @@ you need to use with GitLab. ## SSL -How will you handle SSL in your HA environment? There are several different +How will you handle SSL in your multi-node environment? There are several different options: - Each application node terminates SSL diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index 5405f8d3664..428532337c5 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -204,11 +204,11 @@ Following you'll find some general common practices you will find as part of our ### How to query DOM elements -When it comes to querying DOM elements in your tests, it is best to uniquely target the element, without adding additional attributes specifically for testing purposes. Sometimes this cannot be done feasibly. In these cases, adding test attributes to simplify the selectors might be the best option. +When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target the element. Sometimes this cannot be done feasibly. In these cases, adding test attributes to simplify the selectors might be the best option. Preferentially, in component testing with `@vue/test-utils`, you should query for child components using the component itself. This helps enforce that specific behavior can be covered by that component's individual unit tests. Otherwise, try to use: -- A behavioral attribute like `name` (also verifies that `name` was setup properly) +- A semantic attribute like `name` (also verifies that `name` was setup properly) - A `data-testid` attribute ([recommended by maintainers of `@vue/test-utils`](https://github.com/vuejs/vue-test-utils/issues/1498#issuecomment-610133465)) - a Vue `ref` (if using `@vue/test-utils`) @@ -216,11 +216,17 @@ Examples: ```javascript it('exists', () => { + // Good wrapper.find(FooComponent); wrapper.find('input[name=foo]'); wrapper.find('[data-testid="foo"]'); wrapper.find({ ref: 'foo'}); + + // Bad wrapper.find('.js-foo'); + wrapper.find('.btn-primary'); + wrapper.find('.qa-foo-component'); + wrapper.find('[data-qa-selector="foo"]'); }); ``` diff --git a/doc/install/requirements.md b/doc/install/requirements.md index ba25f73441d..1e2335b808b 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -288,10 +288,11 @@ You can provide feedback [on this issue](https://gitlab.com/gitlab-org/gitlab/-/ GitLab supports the following web browsers: -- Firefox -- Chrome/Chromium -- Safari -- Microsoft Edge +- [Mozilla Firefox](https://www.mozilla.org/firefox/new/) +- [Google Chrome](https://www.google.com/chrome/) +- [Chromium](https://www.chromium.org/getting-involved/dev-channel) +- [Apple Safari](https://www.apple.com/safari/) +- [Microsoft Edge](https://www.microsoft.com/edge) - Internet Explorer 11 (until May 2020) For the listed web browsers, GitLab supports: diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md index 854135aed9f..263f9e54a20 100644 --- a/doc/raketasks/import.md +++ b/doc/raketasks/import.md @@ -115,16 +115,16 @@ repository in GitLab 10.4 and later: - Ancestor renamed - Ancestor transferred to another namespace -Bare repositories are **not** importable by GitLab 10.4 and later when all the following are true about the repository: +Bare repositories are **not** importable by GitLab 10.4 to GitLab 11.6, if all the following are true about the repository: - It was created in GitLab 10.3 or earlier. -- It was not renamed, transferred, or migrated to hashed storage in GitLab 10.4 and later. -- Its ancestor namespaces were not renamed or transferred in GitLab 10.4 and later. +- It was not renamed, transferred, or migrated to [hashed storage](../administration/repository_storage_types.md#hashed-storage) in GitLab 10.4 to GitLab 11.6. +- Its ancestor namespaces were not renamed or transferred in GitLab 10.4 to GitLab 11.6. -There is an [open issue to add a migration to make all bare repositories -importable](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41776). +[Since GitLab 11.6](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41776), all +bare repositories are importable. -Until then, you may wish to manually migrate repositories yourself. You can use +To manually migrate repositories yourself (for GitLab 10.4 to GitLab 11.6), you can use the [Rails console](../administration/troubleshooting/debug.md#starting-a-rails-console-session) to do so. In a Rails console session, run the following to migrate a project: diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md index 427761281f6..417b85a6082 100644 --- a/doc/user/project/merge_requests/accessibility_testing.md +++ b/doc/user/project/merge_requests/accessibility_testing.md @@ -25,16 +25,6 @@ Accessibility Report in the merge request widget area: ![Accessibility Merge Request Widget](img/accessibility_mr_widget_v13_0.png) -This widget comes with the `:accessibility_report_view` feature flag disabled by default while we test feature stability. -Once we have determined the widget is stable, this feature will be enabled by default. - -To enable this feature, ask a GitLab administrator with [Rails console access](../../../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) to run the -following command: - -```ruby -Feature.enable(:accessibility_report_view) -``` - ## Configure Accessibility Testing This example shows how to run [pa11y](https://pa11y.org/) diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml index 47f68118ee0..ae3809f41e8 100644 --- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml @@ -83,7 +83,7 @@ brakeman-sast: $GITLAB_FEATURES =~ /\bsast\b/ && $SAST_DEFAULT_ANALYZERS =~ /brakeman/ exists: - - '**/*.rb' + - 'config/routes.rb' eslint-sast: extends: .sast-analyzer @@ -149,7 +149,7 @@ nodejs-scan-sast: $GITLAB_FEATURES =~ /\bsast\b/ && $SAST_DEFAULT_ANALYZERS =~ /nodejs-scan/ exists: - - '**/*.js' + - 'package.json' phpcs-security-audit-sast: extends: .sast-analyzer @@ -213,8 +213,7 @@ sobelow-sast: $GITLAB_FEATURES =~ /\bsast\b/ && $SAST_DEFAULT_ANALYZERS =~ /sobelow/ exists: - - '**/*.ex' - - '**/*.exs' + - 'mix.exs' spotbugs-sast: extends: .sast-analyzer diff --git a/lib/milestone_array.rb b/lib/milestone_array.rb deleted file mode 100644 index 461e73e9670..00000000000 --- a/lib/milestone_array.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -module MilestoneArray - class << self - def sort(array, sort_method) - case sort_method - when 'due_date_asc' - sort_asc_nulls_last(array, 'due_date') - when 'due_date_desc' - sort_desc_nulls_last(array, 'due_date') - when 'start_date_asc' - sort_asc_nulls_last(array, 'start_date') - when 'start_date_desc' - sort_desc_nulls_last(array, 'start_date') - when 'name_asc' - sort_asc(array, 'title') - when 'name_desc' - sort_asc(array, 'title').reverse - else - array - end - end - - private - - def sort_asc_nulls_last(array, attribute) - attribute = attribute.to_sym - - array.select(&attribute).sort_by(&attribute) + array.reject(&attribute) - end - - def sort_desc_nulls_last(array, attribute) - attribute = attribute.to_sym - - array.select(&attribute).sort_by(&attribute).reverse + array.reject(&attribute) - end - - def sort_asc(array, attribute) - array.sort_by(&attribute.to_sym) - end - end -end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 28c88b14686..20a26662b4a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -20735,9 +20735,6 @@ msgstr "" msgid "Starts at (UTC)" msgstr "" -msgid "State" -msgstr "" - msgid "State your message to activate" msgstr "" diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb index f4b04ad6dee..36c1e2d7169 100644 --- a/spec/controllers/dashboard/milestones_controller_spec.rb +++ b/spec/controllers/dashboard/milestones_controller_spec.rb @@ -8,12 +8,7 @@ describe Dashboard::MilestonesController do let(:user) { create(:user) } let(:project_milestone) { create(:milestone, project: project) } let(:group_milestone) { create(:milestone, group: group) } - let(:milestone) do - DashboardMilestone.build( - [project], - project_milestone.title - ) - end + let(:milestone) { create(:milestone, group: group) } let(:issue) { create(:issue, project: project, milestone: project_milestone) } let(:group_issue) { create(:issue, milestone: group_milestone, project: create(:project, group: group)) } @@ -28,22 +23,6 @@ describe Dashboard::MilestonesController do group.add_developer(user) end - it_behaves_like 'milestone tabs' - - describe "#show" do - render_views - - def view_milestone - get :show, params: { id: milestone.safe_title, title: milestone.title } - end - - it 'shows milestone page' do - view_milestone - - expect(response).to have_gitlab_http_status(:ok) - end - end - describe "#index" do let(:public_group) { create(:group, :public) } let!(:public_milestone) { create(:milestone, group: public_group) } @@ -58,7 +37,6 @@ describe Dashboard::MilestonesController do expect(response).to have_gitlab_http_status(:ok) expect(json_response.size).to eq(2) expect(json_response.map { |i| i["name"] }).to match_array([group_milestone.name, project_milestone.name]) - expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name) end it 'returns closed group and project milestones to which the user belongs' do @@ -67,7 +45,6 @@ describe Dashboard::MilestonesController do expect(response).to have_gitlab_http_status(:ok) expect(json_response.size).to eq(2) expect(json_response.map { |i| i["name"] }).to match_array([closed_group_milestone.name, closed_project_milestone.name]) - expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name) end it 'searches legacy project milestones by title when search_title is given' do diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb index afb950bc538..fa297fa2b5e 100644 --- a/spec/controllers/groups/milestones_controller_spec.rb +++ b/spec/controllers/groups/milestones_controller_spec.rb @@ -8,15 +8,7 @@ describe Groups::MilestonesController do let!(:project2) { create(:project, group: group) } let(:user) { create(:user) } let(:title) { '肯定不是中文的问题' } - let(:milestone) do - project_milestone = create(:milestone, project: project) - - GroupMilestone.build( - group, - [project], - project_milestone.title - ) - end + let(:milestone) { create(:milestone, project: project) } let(:milestone_path) { group_milestone_path(group, milestone.safe_title, title: milestone.title) } let(:milestone_params) do @@ -168,17 +160,16 @@ describe Groups::MilestonesController do context 'as JSON' do let!(:milestone) { create(:milestone, group: group, title: 'group milestone') } - let!(:legacy_milestone1) { create(:milestone, project: project, title: 'legacy') } - let!(:legacy_milestone2) { create(:milestone, project: project2, title: 'legacy') } + let!(:project_milestone1) { create(:milestone, project: project, title: 'same name') } + let!(:project_milestone2) { create(:milestone, project: project2, title: 'same name') } - it 'lists legacy group milestones and group milestones' do + it 'lists project and group milestones' do get :index, params: { group_id: group.to_param }, format: :json milestones = json_response - expect(milestones.count).to eq(2) - expect(milestones.first["title"]).to eq("group milestone") - expect(milestones.second["title"]).to eq("legacy") + expect(milestones.count).to eq(3) + expect(milestones.collect { |m| m['title'] }).to match_array(['same name', 'same name', 'group milestone']) expect(response).to have_gitlab_http_status(:ok) expect(response.content_type).to eq 'application/json' end @@ -191,8 +182,9 @@ describe Groups::MilestonesController do get :index, params: { group_id: group.to_param }, format: :json milestones = json_response - expect(milestones.count).to eq(3) - expect(milestones.second["title"]).to eq("subgroup milestone") + milestone_titles = milestones.map { |m| m['title'] } + expect(milestones.count).to eq(4) + expect(milestone_titles).to match_array(['same name', 'same name', 'group milestone', 'subgroup milestone']) end end @@ -218,31 +210,18 @@ describe Groups::MilestonesController do end describe '#show' do - let(:milestone1) { create(:milestone, project: project, title: 'legacy') } - let(:milestone2) { create(:milestone, project: project, title: 'legacy') } - let(:group_milestone) { create(:milestone, group: group) } + render_views - context 'when there is a title parameter' do - it 'searches for a legacy group milestone' do - expect(GroupMilestone).to receive(:build) - expect(Milestone).not_to receive(:find_by_iid) + let!(:group_milestone) { create(:milestone, group: group) } - get :show, params: { group_id: group.to_param, id: title, title: milestone1.safe_title } - end - end + it 'renders for a group milestone' do + get :show, params: { group_id: group.to_param, id: group_milestone.iid } - context 'when there is not a title parameter' do - it 'searches for a group milestone' do - expect(GlobalMilestone).not_to receive(:build) - expect(Milestone).to receive(:find_by_iid) - - get :show, params: { group_id: group.to_param, id: group_milestone.id } - end + expect(response).to have_gitlab_http_status(:ok) + expect(response.body).to include(group_milestone.title) end end - it_behaves_like 'milestone tabs' - describe "#create" do it "creates group milestone with Chinese title" do post :create, @@ -277,34 +256,6 @@ describe Groups::MilestonesController do expect(response).to redirect_to(group_milestone_path(group, milestone.iid)) expect(milestone.title).to eq("title changed") end - - context "legacy group milestones" do - let!(:milestone1) { create(:milestone, project: project, title: 'legacy milestone', description: "old description") } - let!(:milestone2) { create(:milestone, project: project2, title: 'legacy milestone', description: "old description") } - - it "updates only group milestones state" do - milestone_params[:title] = "title changed" - milestone_params[:description] = "description changed" - milestone_params[:state_event] = "close" - - put :update, - params: { - id: milestone1.title.to_slug.to_s, - group_id: group.to_param, - milestone: milestone_params, - title: milestone1.title - } - - expect(response).to redirect_to(group_milestone_path(group, milestone1.safe_title, title: milestone1.title)) - - [milestone1, milestone2].each do |milestone| - milestone.reload - expect(milestone.title).to eq("legacy milestone") - expect(milestone.description).to eq("old description") - expect(milestone.state).to eq("closed") - end - end - end end describe "#destroy" do diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 7d9e42fcc2d..51cf65e5850 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -1409,20 +1409,6 @@ describe Projects::MergeRequestsController do end end - context 'when feature flag is disabled' do - let(:accessibility_comparison) { { status: :parsed, data: { summary: 1 } } } - - before do - stub_feature_flags(accessibility_report_view: false) - end - - it 'returns 204 HTTP status' do - subject - - expect(response).to have_gitlab_http_status(:no_content) - end - end - context 'when pipeline has jobs with accessibility reports' do before do allow_any_instance_of(MergeRequest) diff --git a/spec/features/dashboard/milestone_tabs_spec.rb b/spec/features/dashboard/milestone_tabs_spec.rb deleted file mode 100644 index a83e4c1f7c9..00000000000 --- a/spec/features/dashboard/milestone_tabs_spec.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe 'Dashboard milestone tabs', :js do - let(:user) { create(:user) } - let(:project) { create(:project) } - let!(:label) { create(:label, project: project) } - let(:project_milestone) { create(:milestone, project: project) } - let(:milestone) do - DashboardMilestone.build( - [project], - project_milestone.title - ) - end - let!(:merge_request) { create(:labeled_merge_request, source_project: project, target_project: project, milestone: project_milestone, labels: [label]) } - - before do - project.add_maintainer(user) - sign_in(user) - - visit dashboard_milestone_path(milestone.safe_title, title: milestone.title) - end - - it 'loads merge requests async' do - click_link 'Merge Requests' - - expect(page).to have_selector('.milestone-merge_requests-list') - end - - it 'loads participants async' do - click_link 'Participants' - - expect(page).to have_selector('#tab-participants .bordered-list') - end - - it 'loads labels async' do - click_link 'Labels' - - expect(page).to have_selector('#tab-labels .bordered-list') - end -end diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb index 65ef0af5be3..b5790c40355 100644 --- a/spec/features/groups/milestone_spec.rb +++ b/spec/features/groups/milestone_spec.rb @@ -102,11 +102,9 @@ describe 'Group milestones' do expect(find('.top-area .all .badge').text).to eq("6") end - it 'lists legacy group milestones and group milestones' do - legacy_milestone = GroupMilestone.build_collection(group, group.projects, { state: 'active' }).first - + it 'lists group and project milestones' do expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1) - expect(page).to have_selector("#milestone_#{legacy_milestone.milestone.id}", count: 1) + expect(page).to have_selector("#milestone_#{active_project_milestone2.id}", count: 1) end it 'shows milestone detail and supports its edit' do @@ -126,74 +124,34 @@ describe 'Group milestones' do expect(page).to have_content('v1.1') expect(page).to have_content('GL-113') expect(page).to have_link( + 'v1.0', + href: project_milestone_path(project, active_project_milestone1) + ) + expect(page).to have_link( '1 Issue', - href: issues_group_path(group, milestone_title: 'v1.0') + href: project_issues_path(project, milestone_title: 'v1.0') ) expect(page).to have_link( '0 Merge Requests', - href: merge_requests_group_path(group, milestone_title: 'v1.0') + href: project_merge_requests_path(project, milestone_title: 'v1.0') + ) + expect(page).to have_link( + 'GL-113', + href: group_milestone_path(group, active_group_milestone) + ) + expect(page).to have_link( + '0 Issues', + href: issues_group_path(group, milestone_title: 'GL-113') + ) + expect(page).to have_link( + '0 Merge Requests', + href: merge_requests_group_path(group, milestone_title: 'GL-113') ) - end - - it 'renders group milestone details' do - click_link 'v1.0' - - expect(page).to have_content('expires on Aug 20, 2114') - expect(page).to have_content('v1.0') - expect(page).to have_content('Issues 1 Open: 1 Closed: 0') - expect(page).to have_link(issue.title, href: project_issue_path(issue.project, issue)) end end end describe 'milestone tabs', :js do - context 'for a legacy group milestone' do - let_it_be(:milestone) { create(:milestone, project: project) } - let_it_be(:label) { create(:label, project: project) } - let_it_be(:issue) { create(:labeled_issue, project: project, milestone: milestone, labels: [label], assignees: [create(:user)]) } - let_it_be(:mr) { create(:merge_request, source_project: project, milestone: milestone) } - - before do - visit group_milestone_path(group, milestone.title, title: milestone.title) - end - - it 'renders the issues tab' do - within('#tab-issues') do - expect(page).to have_content issue.title - end - end - - it 'renders the merge requests tab' do - within('.js-milestone-tabs') do - click_link('Merge Requests') - end - - within('#tab-merge-requests') do - expect(page).to have_content mr.title - end - end - - it 'renders the participants tab' do - within('.js-milestone-tabs') do - click_link('Participants') - end - - within('#tab-participants') do - expect(page).to have_content issue.assignees.first.name - end - end - - it 'renders the labels tab' do - within('.js-milestone-tabs') do - click_link('Labels') - end - - within('#tab-labels') do - expect(page).to have_content label.title - end - end - end - context 'for a group milestone' do let_it_be(:other_project) { create(:project_empty_repo, group: group) } let_it_be(:milestone) { create(:milestone, group: group) } diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb index d27511be0b0..9ebb04e6f97 100644 --- a/spec/features/groups/milestones_sorting_spec.rb +++ b/spec/features/groups/milestones_sorting_spec.rb @@ -24,21 +24,12 @@ describe 'Milestones sorting', :js do # assert default sorting within '.milestones' do - expect(page.all('ul.content-list > li').first.text).to include('v2.0') - expect(page.all('ul.content-list > li')[1].text).to include('v3.0') - expect(page.all('ul.content-list > li').last.text).to include('v1.0') + expect(page.all('ul.content-list > li strong > a').map(&:text)).to eq(['v2.0', 'v2.0', 'v3.0', 'v1.0', 'v1.0']) end click_button 'Due soon' - sort_options = find('ul.dropdown-menu-sort li').all('a').collect(&:text) - - expect(sort_options[0]).to eq('Due soon') - expect(sort_options[1]).to eq('Due later') - expect(sort_options[2]).to eq('Start soon') - expect(sort_options[3]).to eq('Start later') - expect(sort_options[4]).to eq('Name, ascending') - expect(sort_options[5]).to eq('Name, descending') + expect(find('ul.dropdown-menu-sort li').all('a').map(&:text)).to eq(['Due soon', 'Due later', 'Start soon', 'Start later', 'Name, ascending', 'Name, descending']) click_link 'Due later' @@ -46,9 +37,7 @@ describe 'Milestones sorting', :js do # assert descending sorting within '.milestones' do - expect(page.all('ul.content-list > li').first.text).to include('v1.0') - expect(page.all('ul.content-list > li')[1].text).to include('v3.0') - expect(page.all('ul.content-list > li').last.text).to include('v2.0') + expect(page.all('ul.content-list > li strong > a').map(&:text)).to eq(['v1.0', 'v1.0', 'v3.0', 'v2.0', 'v2.0']) end end end diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index bfff33f3956..6956a7e18f6 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -111,20 +111,6 @@ describe 'Milestone' do end end - describe 'deprecation popover', :js do - it 'opens deprecation popover' do - milestone = create(:milestone, project: project) - - visit group_milestone_path(group, milestone, title: milestone.title) - - expect(page).to have_selector('.milestone-deprecation-message') - - find('.milestone-deprecation-message .js-popover-link').click - - expect(page).to have_selector('.popover') - end - end - describe 'reopen closed milestones' do before do create(:milestone, :closed, project: project) diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap index 96028c86269..6bce68af642 100644 --- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap +++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap @@ -14,7 +14,7 @@ exports[`IDE pipeline stage renders stage details & icon 1`] = ` /> <strong - class="prepend-left-8 text-truncate" + class="gl-ml-3 text-truncate" data-container="body" data-original-title="" title="" diff --git a/spec/lib/milestone_array_spec.rb b/spec/lib/milestone_array_spec.rb deleted file mode 100644 index 375cb87dde6..00000000000 --- a/spec/lib/milestone_array_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe MilestoneArray do - let(:object1) { instance_double("BirdMilestone", due_date: Time.now, start_date: Time.now - 15.days, title: 'v2.0') } - let(:object2) { instance_double("CatMilestone", due_date: Time.now - 1.day, start_date: nil, title: 'v1.0') } - let(:object3) { instance_double("DogMilestone", due_date: nil, start_date: Time.now - 30.days, title: 'v3.0') } - let(:array) { [object1, object3, object2] } - - describe '#sort' do - it 'reorders array with due date in ascending order with nulls last' do - expect(described_class.sort(array, 'due_date_asc')).to eq([object2, object1, object3]) - end - - it 'reorders array with due date in desc order with nulls last' do - expect(described_class.sort(array, 'due_date_desc')).to eq([object1, object2, object3]) - end - - it 'reorders array with start date in ascending order with nulls last' do - expect(described_class.sort(array, 'start_date_asc')).to eq([object3, object1, object2]) - end - - it 'reorders array with start date in descending order with nulls last' do - expect(described_class.sort(array, 'start_date_desc')).to eq([object1, object3, object2]) - end - - it 'reorders array with title in ascending order' do - expect(described_class.sort(array, 'name_asc')).to eq([object2, object1, object3]) - end - - it 'reorders array with title in descending order' do - expect(described_class.sort(array, 'name_desc')).to eq([object3, object1, object2]) - end - end -end diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb deleted file mode 100644 index 34dbdfec60d..00000000000 --- a/spec/models/global_milestone_spec.rb +++ /dev/null @@ -1,208 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe GlobalMilestone do - let(:user) { create(:user) } - let(:user2) { create(:user) } - let(:group) { create(:group) } - let(:project1) { create(:project, group: group) } - let(:project2) { create(:project, path: 'gitlab-ci', group: group) } - let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } - - describe '.build_collection' do - let(:milestone1_due_date) { 2.weeks.from_now.to_date } - - let!(:milestone1_project1) do - create( - :milestone, - title: "Milestone v1.2", - project: project1, - due_date: milestone1_due_date - ) - end - - let!(:milestone1_project2) do - create( - :milestone, - title: "Milestone v1.2", - project: project2, - due_date: milestone1_due_date - ) - end - - let!(:milestone1_project3) do - create( - :milestone, - title: "Milestone v1.2", - project: project3, - due_date: milestone1_due_date - ) - end - - let!(:milestone2_project1) do - create( - :milestone, - title: "VD-123", - project: project1, - due_date: nil - ) - end - - let!(:milestone2_project2) do - create( - :milestone, - title: "VD-123", - project: project2, - due_date: nil - ) - end - - let!(:milestone2_project3) do - create( - :milestone, - title: "VD-123", - project: project3, - due_date: nil - ) - end - - let!(:projects) do - [ - project1, - project2, - project3 - ] - end - - let!(:global_milestones) { described_class.build_collection(projects, {}) } - - context 'when building a collection of milestones' do - it 'has all project milestones' do - expect(global_milestones.count).to eq(6) - end - - it 'has all project milestones titles' do - expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2', 'VD-123', 'VD-123', 'VD-123']) - end - - it 'has all project milestones' do - expect(global_milestones.size).to eq(6) - end - - it 'sorts collection by due date' do - expect(global_milestones.map(&:due_date)).to eq [milestone1_due_date, milestone1_due_date, milestone1_due_date, nil, nil, nil] - end - - it 'filters milestones by search_title when params[:search_title] is present' do - global_milestones = described_class.build_collection(projects, { search_title: 'v1.2' }) - - expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2']) - end - end - - context 'when adding new milestones' do - it 'does not add more queries' do - control_count = ActiveRecord::QueryRecorder.new do - described_class.build_collection(projects, {}) - end.count - - create_list(:milestone, 3, project: project3) - - expect do - described_class.build_collection(projects, {}) - end.not_to exceed_all_query_limit(control_count) - end - end - end - - describe '.states_count' do - context 'when the projects have milestones' do - before do - create(:closed_milestone, title: 'Active Group Milestone', project: project3) - create(:active_milestone, title: 'Active Group Milestone', project: project1) - create(:active_milestone, title: 'Active Group Milestone', project: project2) - create(:closed_milestone, title: 'Closed Group Milestone', project: project1) - create(:closed_milestone, title: 'Closed Group Milestone', project: project2) - create(:closed_milestone, title: 'Closed Group Milestone', project: project3) - create(:closed_milestone, title: 'Closed Group Milestone 4', group: group) - end - - it 'returns the quantity of global milestones and group milestones in each possible state' do - expected_count = { opened: 2, closed: 5, all: 7 } - - count = described_class.states_count(Project.all, group) - - expect(count).to eq(expected_count) - end - - it 'returns the quantity of global milestones in each possible state' do - expected_count = { opened: 2, closed: 4, all: 6 } - - count = described_class.states_count(Project.all) - - expect(count).to eq(expected_count) - end - end - - context 'when the projects do not have milestones' do - before do - project1 - end - - it 'returns 0 as the quantity of global milestones in each state' do - expected_count = { opened: 0, closed: 0, all: 0 } - - count = described_class.states_count(Project.all) - - expect(count).to eq(expected_count) - end - end - end - - describe '#initialize' do - let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } - - subject(:global_milestone) { described_class.new(milestone1_project1) } - - it 'has exactly one group milestone' do - expect(global_milestone.title).to eq('Milestone v1.2') - end - - it 'has all project milestones with the same title' do - expect(global_milestone.milestone).to eq(milestone1_project1) - end - end - - describe '#safe_title' do - let(:milestone) { create(:milestone, title: "git / test", project: project1) } - - it 'strips out slashes and spaces' do - global_milestone = described_class.new(milestone) - - expect(global_milestone.safe_title).to eq('git-test') - end - end - - describe '#state' do - context 'when at least one milestone is active' do - it 'returns active' do - title = 'Active Group Milestone' - - global_milestone = described_class.new(create(:active_milestone, title: title)) - - expect(global_milestone.state).to eq('active') - end - end - - context 'when all milestones are closed' do - it 'returns closed' do - title = 'Closed Group Milestone' - - global_milestone = described_class.new(create(:closed_milestone, title: title)) - - expect(global_milestone.state).to eq('closed') - end - end - end -end diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb deleted file mode 100644 index 01856870fe0..00000000000 --- a/spec/models/group_milestone_spec.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe GroupMilestone do - let(:group) { create(:group) } - let(:project) { create(:project, group: group) } - let(:project_milestone) do - create(:milestone, title: "Milestone v1.2", project: project) - end - - describe '.build' do - it 'returns milestone with group assigned' do - milestone = described_class.build( - group, - [project], - project_milestone.title - ) - - expect(milestone.group).to eq group - end - end - - describe '.build_collection' do - let(:group) { create(:group) } - let(:project1) { create(:project, group: group) } - let(:project2) { create(:project, path: 'gitlab-ci', group: group) } - let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } - - let!(:projects) do - [ - project1, - project2, - project3 - ] - end - - it 'returns array of milestones, each with group assigned' do - milestones = described_class.build_collection(group, [project], {}) - expect(milestones).to all(have_attributes(group: group)) - end - - context 'when adding new milestones' do - it 'does not add more queries' do - control_count = ActiveRecord::QueryRecorder.new do - described_class.build_collection(group, projects, {}) - end.count - - create(:milestone, title: 'This title', project: project1) - - expect do - described_class.build_collection(group, projects, {}) - end.not_to exceed_all_query_limit(control_count) - end - end - end -end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index c4e084d4ddb..87d982c1cff 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1651,14 +1651,6 @@ describe MergeRequest do let(:merge_request) { create(:merge_request, :with_accessibility_reports, source_project: project) } it { is_expected.to be_truthy } - - context 'when feature flag is disabled' do - before do - stub_feature_flags(accessibility_report_view: false) - end - - it { is_expected.to be_falsey } - end end context 'when head pipeline does not have accessibility reports' do diff --git a/spec/support/shared_examples/controllers/milestone_tabs_shared_examples.rb b/spec/support/shared_examples/controllers/milestone_tabs_shared_examples.rb index d9656824452..925c45005f0 100644 --- a/spec/support/shared_examples/controllers/milestone_tabs_shared_examples.rb +++ b/spec/support/shared_examples/controllers/milestone_tabs_shared_examples.rb @@ -2,15 +2,7 @@ RSpec.shared_examples 'milestone tabs' do def go(path, extra_params = {}) - params = - case milestone - when DashboardMilestone - { id: milestone.safe_title, title: milestone.title } - when GroupMilestone - { group_id: group.to_param, id: milestone.safe_title, title: milestone.title } - else - { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid } - end + params = { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid } get path, params: params.merge(extra_params) end diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb index 8d7dcfc2416..59406bca813 100644 --- a/spec/views/layouts/_head.html.haml_spec.rb +++ b/spec/views/layouts/_head.html.haml_spec.rb @@ -50,7 +50,7 @@ describe 'layouts/_head' do it 'adds a link preconnect tag' do render - expect(rendered).to match(%Q(<link crossorigin="" href="#{asset_host}" rel="preconnnect">)) + expect(rendered).to match(%Q(<link crossorigin="" href="#{asset_host}" rel="preconnect">)) end end diff --git a/spec/views/shared/milestones/_top.html.haml_spec.rb b/spec/views/shared/milestones/_top.html.haml_spec.rb index 1e209ad6f3f..2d72e278706 100644 --- a/spec/views/shared/milestones/_top.html.haml_spec.rb +++ b/spec/views/shared/milestones/_top.html.haml_spec.rb @@ -12,22 +12,6 @@ describe 'shared/milestones/_top.html.haml' do allow(milestone).to receive(:milestone) { milestone } end - it 'renders a deprecation message for a legacy milestone' do - allow(milestone).to receive(:legacy_group_milestone?) { true } - - render 'shared/milestones/top', milestone: milestone - - expect(rendered).to have_css('.milestone-deprecation-message') - end - - it 'renders a deprecation message for a dashboard milestone' do - allow(milestone).to receive(:dashboard_milestone?) { true } - - render 'shared/milestones/top', milestone: milestone - - expect(rendered).to have_css('.milestone-deprecation-message') - end - it 'does not render a deprecation message for a non-legacy and non-dashboard milestone' do assign :group, group |