diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-27 15:08:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-04-27 15:08:19 +0300 |
commit | 863ba7d77355b305b06112b0c6c3cab3c09898b0 (patch) | |
tree | 6b657c3bfc0cff804fad6094ba61d42c6925c4d4 /app | |
parent | 359bc6940b1205035e14f028b75d0c9c80a1fd5e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
19 files changed, 91 insertions, 94 deletions
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue index 47f25f34d0c..66388f4eb43 100644 --- a/app/assets/javascripts/boards/components/board_list.vue +++ b/app/assets/javascripts/boards/components/board_list.vue @@ -287,7 +287,7 @@ export default { :data-board-type="list.listType" :class="{ 'bg-danger-100': boardItemsSizeExceedsMax }" draggable=".board-card" - class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-2" + class="board-list gl-w-full gl-h-full gl-list-style-none gl-mb-0 gl-p-3 gl-pt-0" data-testid="tree-root-wrapper" @start="handleDragOnStart" @end="handleDragOnEnd" diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue index 9f70c84931f..a4298eb2544 100644 --- a/app/assets/javascripts/boards/components/board_list_header.vue +++ b/app/assets/javascripts/boards/components/board_list_header.vue @@ -126,7 +126,7 @@ export default { return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse; }, chevronIcon() { - return this.list.collapsed ? 'chevron-down' : 'chevron-right'; + return this.list.collapsed ? 'chevron-right' : 'chevron-down'; }, isNewIssueShown() { return (this.listType === ListType.backlog || this.showListHeaderButton) && !this.isEpicBoard; @@ -248,7 +248,6 @@ export default { <template> <header :class="{ - 'has-border': list.label && list.label.color, 'gl-h-full': list.collapsed, 'board-inner gl-rounded-top-left-base gl-rounded-top-right-base': isSwimlanesHeader, }" @@ -279,28 +278,6 @@ export default { @click="toggleExpanded" /> <!-- EE start --> - <span - v-if="showMilestoneListDetails" - aria-hidden="true" - class="milestone-icon" - :class="{ - 'gl-mt-3 gl-rotate-90': list.collapsed, - 'gl-mr-2': !list.collapsed, - }" - > - <gl-icon name="timer" /> - </span> - - <span - v-if="showIterationListDetails" - aria-hidden="true" - :class="{ - 'gl-mt-3 gl-rotate-90': list.collapsed, - 'gl-mr-2': !list.collapsed, - }" - > - <gl-icon name="iteration" /> - </span> <a v-if="showAssigneeListDetails" @@ -399,7 +376,7 @@ export default { <span class="gl-display-inline-flex"> <gl-tooltip :target="() => $refs.itemCount" :title="itemsTooltipLabel" /> <span ref="itemCount" class="gl-display-inline-flex gl-align-items-center"> - <gl-icon class="gl-mr-2" :name="countIcon" /> + <gl-icon class="gl-mr-2" :name="countIcon" :size="16" /> <item-count v-if="!isLoading" :items-size="isEpicBoard ? list.epicsCount : boardList.issuesCount" diff --git a/app/assets/javascripts/diffs/utils/diff_file.js b/app/assets/javascripts/diffs/utils/diff_file.js index a7251bfa775..bcd9fa01278 100644 --- a/app/assets/javascripts/diffs/utils/diff_file.js +++ b/app/assets/javascripts/diffs/utils/diff_file.js @@ -93,6 +93,27 @@ export function getShortShaFromFile(file) { return file.content_sha ? truncateSha(String(file.content_sha)) : null; } +export function match({ fileA, fileB, mode = 'universal' } = {}) { + const matching = { + universal: (a, b) => (a?.id && b?.id ? a.id === b.id : false), + /* + * MR mode can be wildly incorrect if there is ever the possibility of files from multiple MRs + * (e.g. a browser-local merge request/file cache). + * That's why the default here is "universal" mode: UUIDs can't conflict, but you can opt into + * the dangerous one. + * + * For reference: + * file_identifier_hash === sha1( `${filePath}-${Boolean(isNew)}-${Boolean(isDeleted)}-${Boolean(isRenamed)}` ) + */ + mr: (a, b) => + a?.file_identifier_hash && b?.file_identifier_hash + ? a.file_identifier_hash === b.file_identifier_hash + : false, + }; + + return (matching[mode] || (() => false))(fileA, fileB); +} + export function stats(file) { let valid = false; let classes = ''; diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js index a710ac0ccf5..9d184b14878 100644 --- a/app/assets/javascripts/notes/stores/getters.js +++ b/app/assets/javascripts/notes/stores/getters.js @@ -1,4 +1,5 @@ import { flattenDeep, clone } from 'lodash'; +import { match } from '~/diffs/utils/diff_file'; import { statusBoxState } from '~/issuable/components/status_box.vue'; import { isInMRPage } from '~/lib/utils/common_utils'; import * as constants from '../constants'; @@ -179,29 +180,42 @@ export const unresolvedDiscussionsIdsByDate = (state, getters) => // Sorts the array of resolvable yet unresolved discussions by // comparing file names first. If file names are the same, compares // line numbers. -export const unresolvedDiscussionsIdsByDiff = (state, getters) => - getters.allResolvableDiscussions +export const unresolvedDiscussionsIdsByDiff = (state, getters, allState) => { + const authoritativeFiles = allState.diffs.diffFiles; + + return getters.allResolvableDiscussions .filter((d) => !d.resolved && d.active) .sort((a, b) => { + let order = 0; + if (!a.diff_file || !b.diff_file) { - return 0; + return order; } - // Get file names comparison result - const filenameComparison = a.diff_file.file_path.localeCompare(b.diff_file.file_path); + const authoritativeA = authoritativeFiles.find((source) => + match({ fileA: source, fileB: a.diff_file, mode: 'mr' }), + ); + const authoritativeB = authoritativeFiles.find((source) => + match({ fileA: source, fileB: b.diff_file, mode: 'mr' }), + ); + + if (authoritativeA && authoritativeB) { + order = authoritativeA.order - authoritativeB.order; + } // Get the line numbers, to compare within the same file const aLines = [a.position.new_line, a.position.old_line]; const bLines = [b.position.new_line, b.position.old_line]; - return filenameComparison < 0 || - (filenameComparison === 0 && + return order < 0 || + (order === 0 && // .max() because one of them might be zero (if removed/added) Math.max(aLines[0], aLines[1]) < Math.max(bLines[0], bLines[1])) ? -1 : 1; }) .map((d) => d.id); +}; export const resolvedDiscussionCount = (state, getters) => { const resolvedMap = getters.resolvedDiscussionsById; diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss index eecd4954e39..1a968abd6dd 100644 --- a/app/assets/stylesheets/page_bundles/boards.scss +++ b/app/assets/stylesheets/page_bundles/boards.scss @@ -131,8 +131,7 @@ .board-inner { font-size: $issue-boards-font-size; - background: var(--gray-10, $gray-10); - border: 1px solid var(--gray-100, $gray-100); + background: var(--gray-50, $gray-50); } // to highlight columns we have animated pulse of box-shadow @@ -169,33 +168,7 @@ } } -.board-header { - &.has-border::before { - border-top: 3px solid; - border-color: inherit; - border-top-left-radius: $border-radius-default; - border-top-right-radius: $border-radius-default; - content: ''; - position: absolute; - width: calc(100% + 2px); - top: 0; - left: 0; - margin-top: -1px; - margin-right: -1px; - margin-left: -1px; - padding-top: 1px; - padding-right: 1px; - padding-left: 1px; - - .board-title { - padding-top: ($gl-padding - 3px); - padding-bottom: $gl-padding; - } - } -} - .board-title { - border-bottom: 1px solid var(--gray-100, $gray-100); height: 3rem; .max-issue-size::before { @@ -219,7 +192,6 @@ .board-card { background: var(--white, $white); - border: 1px solid var(--gray-100, $gray-100); box-shadow: 0 1px 2px rgba(var(--black, $black), 0.1); line-height: $gl-padding; list-style: none; @@ -239,6 +211,10 @@ background-color: var(--blue-50, $blue-50); } + &.sortable-chosen { + box-shadow: 0 2px 4px 0 rgba($black, 0.16); + } + .gl-label { margin-top: 4px; margin-right: 4px; diff --git a/app/components/pajamas/alert_component.html.haml b/app/components/pajamas/alert_component.html.haml index a1d3c700e57..92bf81a4f8d 100644 --- a/app/components/pajamas/alert_component.html.haml +++ b/app/components/pajamas/alert_component.html.haml @@ -1,5 +1,6 @@ -.gl-alert{ role: 'alert', class: ["gl-alert-#{@variant}", @alert_class], data: @alert_data } - = sprite_icon(icon, css_class: icon_classes) +.gl-alert{ role: 'alert', class: [base_class, @alert_class], data: @alert_data } + - if @show_icon + = sprite_icon(icon, css_class: icon_classes) - if @dismissible %button.btn.gl-dismiss-btn.btn-default.btn-sm.gl-button.btn-default-tertiary.btn-icon.js-close{ type: 'button', aria: { label: _('Dismiss') }, diff --git a/app/components/pajamas/alert_component.rb b/app/components/pajamas/alert_component.rb index 4bb6c41661b..ef35ae195b0 100644 --- a/app/components/pajamas/alert_component.rb +++ b/app/components/pajamas/alert_component.rb @@ -6,22 +6,32 @@ module Pajamas # @param [String] title # @param [Symbol] variant # @param [Boolean] dismissible + # @param [Boolean] show_icon # @param [String] alert_class # @param [Hash] alert_data # @param [String] close_button_class # @param [Hash] close_button_data def initialize( - title: nil, variant: :info, dismissible: true, + title: nil, variant: :info, dismissible: true, show_icon: true, alert_class: nil, alert_data: {}, close_button_class: nil, close_button_data: {}) @title = title @variant = variant @dismissible = dismissible + @show_icon = show_icon @alert_class = alert_class @alert_data = alert_data @close_button_class = close_button_class @close_button_data = close_button_data end + def base_class + classes = ["gl-alert-#{@variant}"] + classes.push('gl-alert-not-dismissible') unless @dismissible + classes.push('gl-alert-no-icon') unless @show_icon + + classes.join(' ') + end + private delegate :sprite_icon, to: :helpers diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 3f4d26bb6ec..8a6202990d4 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -87,7 +87,7 @@ module Projects def permitted_project_params [ :runners_token, :builds_enabled, :build_allow_git_fetch, - :build_timeout_human_readable, :build_coverage_regex, :public_builds, + :build_timeout_human_readable, :public_builds, :auto_cancel_pending_pipelines, :ci_config_path, :auto_rollback_enabled, auto_devops_attributes: [:id, :domain, :enabled, :deploy_strategy], ci_cd_settings_attributes: [:default_git_depth, :forward_deployment_enabled] diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e9dbc69fad3..53e30b97a16 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -420,7 +420,6 @@ class ProjectsController < Projects::ApplicationController :allow_merge_on_skipped_pipeline, :avatar, :build_allow_git_fetch, - :build_coverage_regex, :build_timeout_human_readable, :resolve_outdated_diff_discussions, :container_registry_enabled, diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb index 1ec3cb62c76..ba23d52ca81 100644 --- a/app/models/alert_management/alert.rb +++ b/app/models/alert_management/alert.rb @@ -143,10 +143,6 @@ module AlertManagement reference.to_i > 0 && reference.to_i <= Gitlab::Database::MAX_INT_VALUE end - def metric_images_available? - ::AlertManagement::MetricImage.available_for?(project) - end - def prometheus? monitoring_tool == Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus] end diff --git a/app/models/alert_management/metric_image.rb b/app/models/alert_management/metric_image.rb index 8175a31be7a..4ed28c3b1eb 100644 --- a/app/models/alert_management/metric_image.rb +++ b/app/models/alert_management/metric_image.rb @@ -7,10 +7,6 @@ module AlertManagement belongs_to :alert, class_name: 'AlertManagement::Alert', foreign_key: 'alert_id', inverse_of: :metric_images - def self.available_for?(project) - true - end - private def local_path diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6fb7fe93414..2eb97765a35 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -889,10 +889,6 @@ module Ci job_artifacts.find_by(file_type: file_types_ids)&.file end - def coverage_regex - super || project.try(:build_coverage_regex) - end - def steps [Gitlab::Ci::Build::Step.from_commands(self), Gitlab::Ci::Build::Step.from_release(self), diff --git a/app/models/project.rb b/app/models/project.rb index 84db2b343e6..0b40ce8e46f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -52,6 +52,7 @@ class Project < ApplicationRecord ignore_columns :mirror_last_update_at, :mirror_last_successful_update_at, remove_after: '2021-09-22', remove_with: '14.4' ignore_columns :pull_mirror_branch_prefix, remove_after: '2021-09-22', remove_with: '14.4' + ignore_columns :build_coverage_regex, remove_after: '2022-07-22', remove_with: '15.0' STATISTICS_ATTRIBUTE = 'repositories_count' UNKNOWN_IMPORT_URL = 'http://unknown.git' diff --git a/app/services/alert_management/metric_images/upload_service.rb b/app/services/alert_management/metric_images/upload_service.rb index e9db10594df..46e7e3dbedd 100644 --- a/app/services/alert_management/metric_images/upload_service.rb +++ b/app/services/alert_management/metric_images/upload_service.rb @@ -39,7 +39,7 @@ module AlertManagement private def can_upload_metrics? - alert.metric_images_available? && current_user&.can?(:upload_alert_management_metric_image, alert) + current_user&.can?(:upload_alert_management_metric_image, alert) end end end diff --git a/app/services/import/bitbucket_server_service.rb b/app/services/import/bitbucket_server_service.rb index cdb23370ddc..d1c22f06464 100644 --- a/app/services/import/bitbucket_server_service.rb +++ b/app/services/import/bitbucket_server_service.rb @@ -21,6 +21,8 @@ module Import if project.persisted? success(project) + elsif project.errors[:import_source_disabled].present? + error(project.errors[:import_source_disabled], :forbidden) else log_and_return_error(project_save_error(project), :unprocessable_entity) end diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb index a891dcc11e3..033f6bcb043 100644 --- a/app/services/import/github_service.rb +++ b/app/services/import/github_service.rb @@ -25,6 +25,8 @@ module Import if project.persisted? success(project) + elsif project.errors[:import_source_disabled].present? + error(project.errors[:import_source_disabled], :forbidden) else error(project_save_error(project), :unprocessable_entity) end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index a601cbb3a3e..997841fc7d5 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -4,6 +4,9 @@ module Projects class CreateService < BaseService include ValidatesClassificationLabel + ImportSourceDisabledError = Class.new(StandardError) + INTERNAL_IMPORT_SOURCES = %w[bare_repository gitlab_custom_project_template gitlab_project_migration].freeze + def initialize(user, params) @current_user = user @params = params.dup @@ -25,6 +28,8 @@ module Projects @project = Project.new(params) + validate_import_source_enabled! + @project.visibility_level = @project.group.visibility_level unless @project.visibility_level_allowed_by_group? # If a project is newly created it should have shared runners settings @@ -77,6 +82,9 @@ module Projects rescue ActiveRecord::RecordInvalid => e message = "Unable to save #{e.inspect}: #{e.record.errors.full_messages.join(", ")}" fail(error: message) + rescue ImportSourceDisabledError => e + @project.errors.add(:import_source_disabled, e.message) if @project + fail(error: e.message) rescue StandardError => e @project.errors.add(:base, e.message) if @project fail(error: e.message) @@ -238,6 +246,16 @@ module Projects private + def validate_import_source_enabled! + return unless @params[:import_type] + + return if INTERNAL_IMPORT_SOURCES.include?(@params[:import_type]) + + unless ::Gitlab::CurrentSettings.import_sources&.include?(@params[:import_type]) + raise ImportSourceDisabledError, "#{@params[:import_type]} import source is disabled" + end + end + def parent_namespace @parent_namespace ||= Namespace.find_by_id(@params[:namespace_id]) || current_user.namespace end diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml index 5ef56cda6d2..3285fb609e2 100644 --- a/app/views/projects/settings/ci_cd/_form.html.haml +++ b/app/views/projects/settings/ci_cd/_form.html.haml @@ -77,19 +77,7 @@ = _("The maximum file size in megabytes for individual job artifacts.") = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank', rel: 'noopener noreferrer' - .form-group - = f.label :build_coverage_regex, _("Test coverage parsing"), class: 'label-bold' - .input-group - %span.input-group-prepend - .input-group-text / - = f.text_field :build_coverage_regex, class: 'form-control gl-form-input', placeholder: 'Regular expression', data: { qa_selector: 'build_coverage_regex_field' } - %span.input-group-append - .input-group-text / - %p.form-text.text-muted - = html_escape(_('The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable.')) % { regex: '<code>\(\d+.\d+%\)</code>'.html_safe } - = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'add-test-coverage-results-using-project-settings-deprecated'), target: '_blank', rel: 'noopener noreferrer' - - = f.submit _('Save changes'), class: "btn gl-button btn-confirm", data: { qa_selector: 'save_general_pipelines_changes_button' } + = f.submit _('Save changes'), class: "btn gl-button btn-confirm" %hr diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml index 28cde994d00..5238c712a41 100644 --- a/app/views/projects/settings/ci_cd/show.html.haml +++ b/app/views/projects/settings/ci_cd/show.html.haml @@ -7,7 +7,7 @@ - expanded = expanded_by_default? - general_expanded = @project.errors.empty? ? expanded : true -%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded), data: { qa_selector: 'general_pipelines_settings_content' } } +%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) } .settings-header %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only = _("General pipelines") |