Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-01-08 15:10:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-01-08 15:10:35 +0300
commit9157fbe06fde892c647403f477ce31c888cbc822 (patch)
tree81e50784fb79e9f3e467aac46c37cfcc5c7267b3 /app
parent32e1683f8b0b5b5bb24986adeb99118ceb875ea5 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue4
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue41
-rw-r--r--app/assets/javascripts/members/constants.js2
-rw-r--r--app/controllers/projects/pipelines/tests_controller.rb2
-rw-r--r--app/mailers/emails/pipelines.rb15
-rw-r--r--app/services/boards/base_items_list_service.rb128
-rw-r--r--app/services/boards/issues/list_service.rb111
-rw-r--r--app/services/projects/container_repository/gitlab/delete_tags_service.rb2
-rw-r--r--app/views/notify/pipeline_failed_email.html.haml2
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb2
-rw-r--r--app/views/notify/pipeline_fixed_email.html.haml2
-rw-r--r--app/views/notify/pipeline_fixed_email.text.erb2
-rw-r--r--app/views/notify/pipeline_success_email.html.haml2
-rw-r--r--app/views/notify/pipeline_success_email.text.erb2
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;" }
&nbsp;
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!" -%>