diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-08 15:10:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-08 15:10:35 +0300 |
commit | 9157fbe06fde892c647403f477ce31c888cbc822 (patch) | |
tree | 81e50784fb79e9f3e467aac46c37cfcc5c7267b3 /app | |
parent | 32e1683f8b0b5b5bb24986adeb99118ceb875ea5 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
14 files changed, 191 insertions, 126 deletions
diff --git a/app/assets/javascripts/alert_management/components/alert_management_table.vue b/app/assets/javascripts/alert_management/components/alert_management_table.vue index d6e31b57cba..2bad15faa85 100644 --- a/app/assets/javascripts/alert_management/components/alert_management_table.vue +++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue @@ -23,7 +23,7 @@ import { } from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import { convertToSnakeCase } from '~/lib/utils/text_utility'; -import getAlerts from '~/graphql_shared/queries/get_alerts.query.graphql'; +import getAlertsQuery from '~/graphql_shared/queries/get_alerts.query.graphql'; import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql'; import { ALERTS_STATUS_TABS, @@ -119,7 +119,7 @@ export default { apollo: { alerts: { fetchPolicy: fetchPolicies.CACHE_AND_NETWORK, - query: getAlerts, + query: getAlertsQuery, variables() { return { searchTerm: this.searchTerm, diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue index 0c79bf06d64..16e0cd5ad4e 100644 --- a/app/assets/javascripts/members/components/table/members_table.vue +++ b/app/assets/javascripts/members/components/table/members_table.vue @@ -36,7 +36,14 @@ export default { filteredFields() { return FIELDS.filter( (field) => this.tableFields.includes(field.key) && this.showField(field), - ); + ).map((field) => { + const tdClassFunction = this[field.tdClassFunction]; + + return { + ...field, + ...(tdClassFunction && { tdClass: tdClassFunction }), + }; + }); }, userIsLoggedIn() { return this.currentUserId !== null; @@ -46,6 +53,14 @@ export default { initUserPopovers(this.$el.querySelectorAll('.js-user-link')); }, methods: { + hasActionButtons(member) { + return ( + canRemove(member, this.sourceId) || + canResend(member) || + canUpdate(member, this.currentUserId, this.sourceId) || + canOverride(member) + ); + }, showField(field) { if (!Object.prototype.hasOwnProperty.call(field, 'showFunction')) { return true; @@ -58,14 +73,20 @@ export default { return false; } - return this.members.some((member) => { - return ( - canRemove(member, this.sourceId) || - canResend(member) || - canUpdate(member, this.currentUserId, this.sourceId) || - canOverride(member) - ); - }); + return this.members.some((member) => this.hasActionButtons(member)); + }, + tdClassActions(value, key, member) { + if (this.hasActionButtons(member)) { + return 'col-actions'; + } + + return ['col-actions', 'gl-display-none!', 'gl-display-lg-table-cell!']; + }, + tbodyTrAttr(member) { + return { + ...this.tableAttrs.tr, + ...(member?.id && { 'data-testid': `members-table-row-${member.id}` }), + }; }, }, }; @@ -85,7 +106,7 @@ export default { thead-class="border-bottom" :empty-text="__('No members found')" show-empty - :tbody-tr-attr="tableAttrs.tr" + :tbody-tr-attr="tbodyTrAttr" > <template #cell(account)="{ item: member }"> <members-table-cell #default="{ memberType, isCurrentUser }" :member="member"> diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js index 21af825f795..77cb150bff6 100644 --- a/app/assets/javascripts/members/constants.js +++ b/app/assets/javascripts/members/constants.js @@ -70,8 +70,8 @@ export const FIELDS = [ { key: 'actions', thClass: 'col-actions', - tdClass: 'col-actions', showFunction: 'showActionsField', + tdClassFunction: 'tdClassActions', }, ]; diff --git a/app/controllers/projects/pipelines/tests_controller.rb b/app/controllers/projects/pipelines/tests_controller.rb index 1c212964df5..924d52898ea 100644 --- a/app/controllers/projects/pipelines/tests_controller.rb +++ b/app/controllers/projects/pipelines/tests_controller.rb @@ -6,6 +6,8 @@ module Projects before_action :authorize_read_build! before_action :builds, only: [:show] + feature_category :code_testing + def summary respond_to do |format| format.json do diff --git a/app/mailers/emails/pipelines.rb b/app/mailers/emails/pipelines.rb index f2538d28a1a..0b830f4ee5e 100644 --- a/app/mailers/emails/pipelines.rb +++ b/app/mailers/emails/pipelines.rb @@ -3,15 +3,15 @@ module Emails module Pipelines def pipeline_success_email(pipeline, recipients) - pipeline_mail(pipeline, recipients, 'succeeded') + pipeline_mail(pipeline, recipients, 'Succesful') end def pipeline_failed_email(pipeline, recipients) - pipeline_mail(pipeline, recipients, 'failed') + pipeline_mail(pipeline, recipients, 'Failed') end def pipeline_fixed_email(pipeline, recipients) - pipeline_mail(pipeline, recipients, 'been fixed') + pipeline_mail(pipeline, recipients, 'Fixed') end private @@ -50,10 +50,13 @@ module Emails end def pipeline_subject(status) - commit = [@pipeline.short_sha] - commit << "in #{@merge_request.to_reference}" if @merge_request + subject = [] - subject("Pipeline ##{@pipeline.id} has #{status} for #{@pipeline.source_ref}", commit.join(' ')) + subject << "#{status} pipeline for #{@pipeline.source_ref}" + subject << @project.name if @project + subject << @pipeline.short_sha + + subject.join(' | ') end end end diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb new file mode 100644 index 00000000000..851120ef597 --- /dev/null +++ b/app/services/boards/base_items_list_service.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +module Boards + class BaseItemsListService < Boards::BaseService + include Gitlab::Utils::StrongMemoize + include ActiveRecord::ConnectionAdapters::Quoting + + def execute + return items.order_closed_date_desc if list&.closed? + + ordered_items + end + + private + + def ordered_items + raise NotImplementedError + end + + def finder + raise NotImplementedError + end + + def board + raise NotImplementedError + end + + def item_model + raise NotImplementedError + end + + # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query. + # rubocop: disable CodeReuse/ActiveRecord + def items + strong_memoize(:items) do + filter(finder.execute).reorder(nil) + end + end + # rubocop: enable CodeReuse/ActiveRecord + + def filter(items) + # when grouping board issues by epics (used in board swimlanes) + # we need to get all issues in the board + # TODO: ignore hidden columns - + # https://gitlab.com/gitlab-org/gitlab/-/issues/233870 + return items if params[:all_lists] + + items = without_board_labels(items) unless list&.movable? || list&.closed? + items = with_list_label(items) if list&.label? + items + end + + def list + return unless params.key?(:id) + + strong_memoize(:list) do + id = params[:id] + + if board.lists.loaded? + board.lists.find { |l| l.id == id } + else + board.lists.find(id) + end + end + end + + def filter_params + set_parent + set_state + set_attempt_search_optimizations + + params + end + + def set_parent + if parent.is_a?(Group) + params[:group_id] = parent.id + else + params[:project_id] = parent.id + end + end + + def set_state + return if params[:all_lists] + + params[:state] = list && list.closed? ? 'closed' : 'opened' + end + + def set_attempt_search_optimizations + return unless params[:search].present? + + if board.group_board? + params[:attempt_group_search_optimizations] = true + else + params[:attempt_project_search_optimizations] = true + end + end + + # rubocop: disable CodeReuse/ActiveRecord + def board_label_ids + @board_label_ids ||= board.lists.movable.pluck(:label_id) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def without_board_labels(items) + return items unless board_label_ids.any? + + items.where.not('EXISTS (?)', label_links(board_label_ids).limit(1)) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def label_links(label_ids) + LabelLink + .where('label_links.target_type = ?', item_model) + .where(item_model.arel_table[:id].eq(LabelLink.arel_table[:target_id]).to_sql) + .where(label_id: label_ids) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def with_list_label(items) + items.where('EXISTS (?)', label_links(list.label_id).limit(1)) + end + # rubocop: enable CodeReuse/ActiveRecord + end +end diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb index ab9d11abe98..27d59e052c7 100644 --- a/app/services/boards/issues/list_service.rb +++ b/app/services/boards/issues/list_service.rb @@ -2,26 +2,20 @@ module Boards module Issues - class ListService < Boards::BaseService + class ListService < Boards::BaseItemsListService include Gitlab::Utils::StrongMemoize def self.valid_params IssuesFinder.valid_params end - def execute - return fetch_issues.order_closed_date_desc if list&.closed? - - fetch_issues.order_by_position_and_priority(with_cte: params[:search].present?) - end - # rubocop: disable CodeReuse/ActiveRecord def metadata issues = Issue.arel_table keys = metadata_fields.keys # TODO: eliminate need for SQL literal fragment columns = Arel.sql(metadata_fields.values_at(*keys).join(', ')) - results = Issue.where(id: fetch_issues.select(issues[:id])).pluck(columns) + results = Issue.where(id: items.select(issues[:id])).pluck(columns) Hash[keys.zip(results.flatten)] end @@ -29,74 +23,28 @@ module Boards private - def metadata_fields - { size: 'COUNT(*)' } - end - - # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query. - # rubocop: disable CodeReuse/ActiveRecord - def fetch_issues - strong_memoize(:fetch_issues) do - issues = IssuesFinder.new(current_user, filter_params).execute - - filter(issues).reorder(nil) - end + def ordered_items + items.order_by_position_and_priority(with_cte: params[:search].present?) end - # rubocop: enable CodeReuse/ActiveRecord - def filter(issues) - # when grouping board issues by epics (used in board swimlanes) - # we need to get all issues in the board - # TODO: ignore hidden columns - - # https://gitlab.com/gitlab-org/gitlab/-/issues/233870 - return issues if params[:all_lists] - - issues = without_board_labels(issues) unless list&.movable? || list&.closed? - issues = with_list_label(issues) if list&.label? - issues + def finder + IssuesFinder.new(current_user, filter_params) end def board @board ||= parent.boards.find(params[:board_id]) end - def list - return unless params.key?(:id) - - strong_memoize(:list) do - id = params[:id] - - if board.lists.loaded? - board.lists.find { |l| l.id == id } - else - board.lists.find(id) - end - end + def metadata_fields + { size: 'COUNT(*)' } end def filter_params - set_parent - set_state set_scope set_non_archived - set_attempt_search_optimizations set_issue_types - params - end - - def set_parent - if parent.is_a?(Group) - params[:group_id] = parent.id - else - params[:project_id] = parent.id - end - end - - def set_state - return if params[:all_lists] - - params[:state] = list && list.closed? ? 'closed' : 'opened' + super end def set_scope @@ -107,49 +55,12 @@ module Boards params[:non_archived] = parent.is_a?(Group) end - def set_attempt_search_optimizations - return unless params[:search].present? - - if board.group_board? - params[:attempt_group_search_optimizations] = true - else - params[:attempt_project_search_optimizations] = true - end - end - def set_issue_types params[:issue_types] = Issue::TYPES_FOR_LIST end - # rubocop: disable CodeReuse/ActiveRecord - def board_label_ids - @board_label_ids ||= board.lists.movable.pluck(:label_id) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def without_board_labels(issues) - return issues unless board_label_ids.any? - - issues.where.not('EXISTS (?)', issues_label_links.limit(1)) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def issues_label_links - LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id").where(label_id: board_label_ids) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def with_list_label(issues) - issues.where('EXISTS (?)', LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id") - .where("label_links.label_id = ?", list.label_id).limit(1)) - end - # rubocop: enable CodeReuse/ActiveRecord - - def board_group - board.group_board? ? parent : parent.group + def item_model + Issue end end end diff --git a/app/services/projects/container_repository/gitlab/delete_tags_service.rb b/app/services/projects/container_repository/gitlab/delete_tags_service.rb index cc7de7eb776..589aac5c3ac 100644 --- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb +++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb @@ -24,7 +24,7 @@ module Projects return success(deleted: []) if @tag_names.empty? delete_tags - rescue => e + rescue TimeoutError, ::Faraday::Error => e ::Gitlab::ErrorTracking.track_exception(e, tags_count: @tag_names&.size, container_repository_id: @container_repository&.id) error('error while deleting tags', nil, pass_back: { deleted: @deleted_tags, exception_class_name: e.class.name }) end diff --git a/app/views/notify/pipeline_failed_email.html.haml b/app/views/notify/pipeline_failed_email.html.haml index 575ec8c488e..4e8d8a20ef1 100644 --- a/app/views/notify/pipeline_failed_email.html.haml +++ b/app/views/notify/pipeline_failed_email.html.haml @@ -6,7 +6,7 @@ %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;line-height:1;" } %img{ alt: "✖", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-x-red-inverted.gif'), style: "display:block;", width: "13" }/ %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" } - Your pipeline has failed. + Pipeline ##{@pipeline.id} has failed! %tr.spacer %td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" } diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb index a30e331d892..2deca375db1 100644 --- a/app/views/notify/pipeline_failed_email.text.erb +++ b/app/views/notify/pipeline_failed_email.text.erb @@ -1,4 +1,4 @@ -Your pipeline has failed. +Pipeline #<%= @pipeline.id %> has failed! Project: <%= @project.name %> ( <%= project_url(@project) %> ) Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> ) diff --git a/app/views/notify/pipeline_fixed_email.html.haml b/app/views/notify/pipeline_fixed_email.html.haml index 05c0027a6fc..f2dbb3b20b7 100644 --- a/app/views/notify/pipeline_fixed_email.html.haml +++ b/app/views/notify/pipeline_fixed_email.html.haml @@ -1 +1 @@ -= render 'notify/successful_pipeline', title: 'Your pipeline has been fixed!' += render 'notify/successful_pipeline', title: "Pipeline has been fixed and ##{@pipeline.id} has passed!" diff --git a/app/views/notify/pipeline_fixed_email.text.erb b/app/views/notify/pipeline_fixed_email.text.erb index 75268531bdc..32334260a5e 100644 --- a/app/views/notify/pipeline_fixed_email.text.erb +++ b/app/views/notify/pipeline_fixed_email.text.erb @@ -1 +1 @@ -<%= render 'notify/successful_pipeline', title: 'Your pipeline has been fixed!' -%> +<%= render 'notify/successful_pipeline', title: "Pipeline has been fixed and ##{@pipeline.id} has passed!" -%> diff --git a/app/views/notify/pipeline_success_email.html.haml b/app/views/notify/pipeline_success_email.html.haml index c34e02b5fee..47832907663 100644 --- a/app/views/notify/pipeline_success_email.html.haml +++ b/app/views/notify/pipeline_success_email.html.haml @@ -1 +1 @@ -= render 'notify/successful_pipeline', title: 'Your pipeline has passed.' += render 'notify/successful_pipeline', title: "Pipeline ##{@pipeline.id} has passed!" diff --git a/app/views/notify/pipeline_success_email.text.erb b/app/views/notify/pipeline_success_email.text.erb index b554bffc908..83cdb72d252 100644 --- a/app/views/notify/pipeline_success_email.text.erb +++ b/app/views/notify/pipeline_success_email.text.erb @@ -1 +1 @@ -<%= render 'notify/successful_pipeline', title: 'Your pipeline has passed.' -%> +<%= render 'notify/successful_pipeline', title: "Pipeline ##{@pipeline.id} has passed!" -%> |