Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-01-27 21:08:47 +00:00
parent 390582e118
commit e4ea43b2b8
62 changed files with 427 additions and 408 deletions

View File

@ -52,14 +52,6 @@ Layout/ClosingParenthesisIndentation:
- 'spec/support/helpers/stub_object_storage.rb' - 'spec/support/helpers/stub_object_storage.rb'
- 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb' - 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: leading, trailing
Layout/DotPosition:
Exclude:
- 'app/models/concerns/relative_positioning.rb'
# Offense count: 69 # Offense count: 69
# Cop supports --auto-correct. # Cop supports --auto-correct.
Layout/EmptyLinesAroundArguments: Layout/EmptyLinesAroundArguments:
@ -100,12 +92,6 @@ Layout/IndentFirstParameter:
- 'spec/support/helpers/repo_helpers.rb' - 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/stub_object_storage.rb' - 'spec/support/helpers/stub_object_storage.rb'
# Offense count: 1
# Cop supports --auto-correct.
Layout/LeadingBlankLines:
Exclude:
- 'lib/tasks/yarn.rake'
# Offense count: 54 # Offense count: 54
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth. # Configuration parameters: EnforcedStyle, IndentationWidth.
@ -150,11 +136,6 @@ Layout/SpaceInsideBlockBraces:
Layout/SpaceInsideParens: Layout/SpaceInsideParens:
Enabled: false Enabled: false
# Offense count: 1
Lint/DisjunctiveAssignmentInConstructor:
Exclude:
- 'app/models/uploads/base.rb'
# Offense count: 19 # Offense count: 19
Lint/DuplicateMethods: Lint/DuplicateMethods:
Exclude: Exclude:
@ -177,21 +158,6 @@ Lint/DuplicateMethods:
Lint/MissingCopEnableDirective: Lint/MissingCopEnableDirective:
Enabled: false Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: Whitelist.
# Whitelist: present?, blank?, presence, try, try!
Lint/SafeNavigationConsistency:
Exclude:
- 'lib/gitlab/gpg/commit.rb'
# Offense count: 2
# Cop supports --auto-correct.
Lint/ToJSON:
Exclude:
- 'lib/gitlab/cycle_analytics/usage_data.rb'
- 'lib/gitlab/template/base_template.rb'
# Offense count: 6 # Offense count: 6
Lint/UriEscapeUnescape: Lint/UriEscapeUnescape:
Exclude: Exclude:
@ -200,12 +166,6 @@ Lint/UriEscapeUnescape:
- 'spec/lib/google_api/auth_spec.rb' - 'spec/lib/google_api/auth_spec.rb'
- 'spec/requests/api/files_spec.rb' - 'spec/requests/api/files_spec.rb'
# Offense count: 1
# Configuration parameters: CheckForMethodsWithNoSideEffects.
Lint/Void:
Exclude:
- 'lib/gitlab/git/diff_collection.rb'
# Offense count: 165 # Offense count: 165
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
@ -284,12 +244,6 @@ RSpec/LetBeforeExamples:
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb' - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/serializers/pipeline_details_entity_spec.rb' - 'spec/serializers/pipeline_details_entity_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
RSpec/MultipleSubjects:
Exclude:
- 'spec/services/merge_requests/create_from_issue_service_spec.rb'
# Offense count: 2018 # Offense count: 2018
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers. # Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
@ -319,12 +273,6 @@ RSpec/ScatteredSetup:
- 'spec/requests/api/jobs_spec.rb' - 'spec/requests/api/jobs_spec.rb'
- 'spec/services/projects/create_service_spec.rb' - 'spec/services/projects/create_service_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
RSpec/SharedContext:
Exclude:
- 'spec/features/admin/admin_groups_spec.rb'
# Offense count: 4 # Offense count: 4
RSpec/VoidExpect: RSpec/VoidExpect:
Exclude: Exclude:
@ -348,12 +296,6 @@ Rails/ApplicationController:
- 'spec/controllers/concerns/continue_params_spec.rb' - 'spec/controllers/concerns/continue_params_spec.rb'
- 'spec/lib/marginalia_spec.rb' - 'spec/lib/marginalia_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
Rails/ApplicationMailer:
Exclude:
- 'app/mailers/base_mailer.rb'
# Offense count: 8 # Offense count: 8
# Cop supports --auto-correct. # Cop supports --auto-correct.
Rails/BelongsTo: Rails/BelongsTo:
@ -414,14 +356,6 @@ Rails/LinkToBlank:
Rails/RakeEnvironment: Rails/RakeEnvironment:
Enabled: false Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/RedundantAllowNil:
Exclude:
- 'app/models/application_setting.rb'
# Offense count: 868 # Offense count: 868
# Configuration parameters: Blacklist, Whitelist. # Configuration parameters: Blacklist, Whitelist.
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters # Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
@ -457,12 +391,6 @@ Style/CommentedKeyword:
- 'lib/tasks/gitlab/backup.rake' - 'lib/tasks/gitlab/backup.rake'
- 'spec/tasks/gitlab/backup_rake_spec.rb' - 'spec/tasks/gitlab/backup_rake_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/Dir:
Exclude:
- 'qa/qa.rb'
# Offense count: 6 # Offense count: 6
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/EachWithObject: Style/EachWithObject:
@ -591,13 +519,6 @@ Style/NumericLiteralPrefix:
Style/NumericPredicate: Style/NumericPredicate:
Enabled: false Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
Style/OrAssignment:
Exclude:
- 'lib/api/commit_statuses.rb'
- 'lib/gitlab/project_transfer.rb'
# Offense count: 106 # Offense count: 106
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/ParallelAssignment: Style/ParallelAssignment:
@ -632,12 +553,6 @@ Style/PerlBackrefs:
Style/RaiseArgs: Style/RaiseArgs:
Enabled: false Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
Style/RedundantConditional:
Exclude:
- 'lib/system_check/helpers.rb'
# Offense count: 221 # Offense count: 221
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/RedundantFreeze: Style/RedundantFreeze:
@ -704,12 +619,6 @@ Style/SingleLineMethods:
Style/SpecialGlobalVars: Style/SpecialGlobalVars:
EnforcedStyle: use_perl_names EnforcedStyle: use_perl_names
# Offense count: 1
# Cop supports --auto-correct.
Style/StderrPuts:
Exclude:
- 'config/initializers/rspec_profiling.rb'
# Offense count: 75 # Offense count: 75
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@ -736,30 +645,6 @@ Style/TernaryParentheses:
- 'spec/requests/api/pipeline_schedules_spec.rb' - 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/support/capybara.rb' - 'spec/support/capybara.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInArrayLiteral:
Exclude:
- 'ee/spec/models/project_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/processor_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyleForMultiline.
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
Style/TrailingCommaInHashLiteral:
Exclude:
- 'lib/gitlab/ci/ansi2html.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/UnlessElse:
Exclude:
- 'lib/backup/manager.rb'
- 'lib/gitlab/project_search_results.rb'
# Offense count: 8 # Offense count: 8
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/UnneededCondition: Style/UnneededCondition:
@ -776,13 +661,6 @@ Style/UnneededCondition:
Style/UnneededInterpolation: Style/UnneededInterpolation:
Enabled: false Enabled: false
# Offense count: 2
# Cop supports --auto-correct.
Style/UnneededSort:
Exclude:
- 'app/models/concerns/resolvable_discussion.rb'
- 'lib/gitlab/highlight.rb'
RSpec/ReceiveCounts: RSpec/ReceiveCounts:
Exclude: Exclude:
- 'ee/spec/models/broadcast_message_spec.rb' - 'ee/spec/models/broadcast_message_spec.rb'
@ -907,4 +785,4 @@ RSpec/ContextMethod:
- 'spec/services/projects/open_issues_count_service_spec.rb' - 'spec/services/projects/open_issues_count_service_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb' - 'spec/services/quick_actions/interpret_service_spec.rb'
- 'spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb' - 'spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb'
- 'spec/uploaders/namespace_file_uploader_spec.rb' - 'spec/uploaders/namespace_file_uploader_spec.rb'

View File

@ -132,11 +132,6 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
environmentsEndpoint: {
type: String,
required: false,
default: '',
},
currentEnvironmentName: { currentEnvironmentName: {
type: String, type: String,
required: true, required: true,
@ -218,9 +213,7 @@ export default {
]), ]),
...mapGetters('monitoringDashboard', ['getMetricStates', 'filteredEnvironments']), ...mapGetters('monitoringDashboard', ['getMetricStates', 'filteredEnvironments']),
firstDashboard() { firstDashboard() {
return this.environmentsEndpoint.length > 0 && this.allDashboards.length > 0 return this.allDashboards.length > 0 ? this.allDashboards[0] : {};
? this.allDashboards[0]
: {};
}, },
selectedDashboard() { selectedDashboard() {
return this.allDashboards.find(d => d.path === this.currentDashboard) || this.firstDashboard; return this.allDashboards.find(d => d.path === this.currentDashboard) || this.firstDashboard;
@ -246,7 +239,6 @@ export default {
created() { created() {
this.setEndpoints({ this.setEndpoints({
metricsEndpoint: this.metricsEndpoint, metricsEndpoint: this.metricsEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
deploymentsEndpoint: this.deploymentsEndpoint, deploymentsEndpoint: this.deploymentsEndpoint,
dashboardEndpoint: this.dashboardEndpoint, dashboardEndpoint: this.dashboardEndpoint,
dashboardsEndpoint: this.dashboardsEndpoint, dashboardsEndpoint: this.dashboardsEndpoint,

View File

@ -172,7 +172,6 @@ export default {
[types.SET_ENDPOINTS](state, endpoints) { [types.SET_ENDPOINTS](state, endpoints) {
state.metricsEndpoint = endpoints.metricsEndpoint; state.metricsEndpoint = endpoints.metricsEndpoint;
state.environmentsEndpoint = endpoints.environmentsEndpoint;
state.deploymentsEndpoint = endpoints.deploymentsEndpoint; state.deploymentsEndpoint = endpoints.deploymentsEndpoint;
state.dashboardEndpoint = endpoints.dashboardEndpoint; state.dashboardEndpoint = endpoints.dashboardEndpoint;
state.dashboardsEndpoint = endpoints.dashboardsEndpoint; state.dashboardsEndpoint = endpoints.dashboardsEndpoint;

View File

@ -2,7 +2,6 @@ import invalidUrl from '~/lib/utils/invalid_url';
export default () => ({ export default () => ({
metricsEndpoint: null, metricsEndpoint: null,
environmentsEndpoint: null,
deploymentsEndpoint: null, deploymentsEndpoint: null,
dashboardEndpoint: invalidUrl, dashboardEndpoint: invalidUrl,
emptyState: 'gettingStarted', emptyState: 'gettingStarted',

View File

@ -1,12 +1,8 @@
<script> <script>
import { GlButton } from '@gitlab/ui';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue'; import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import Icon from '~/vue_shared/components/icon.vue';
export default { export default {
components: { components: {
Icon,
GlButton,
ClipboardButton, ClipboardButton,
}, },
props: { props: {
@ -26,13 +22,5 @@ export default {
:title="s__('ServerlessURL|Copy URL')" :title="s__('ServerlessURL|Copy URL')"
class="input-group-text js-clipboard-btn" class="input-group-text js-clipboard-btn"
/> />
<gl-button
:href="uri"
target="_blank"
rel="noopener noreferrer nofollow"
class="input-group-text btn btn-default"
>
<icon name="external-link" />
</gl-button>
</div> </div>
</template> </template>

View File

@ -146,9 +146,15 @@ export default {
auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined, auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined,
should_remove_source_branch: this.removeSourceBranch === true, should_remove_source_branch: this.removeSourceBranch === true,
squash: this.squashBeforeMerge, squash: this.squashBeforeMerge,
squash_commit_message: this.squashCommitMessage,
}; };
// If users can't alter the squash message (e.g. for 1-commit merge requests),
// we shouldn't send the commit message because that would make the backend
// do unnecessary work.
if (this.shouldShowSquashBeforeMerge) {
options.squash_commit_message = this.squashCommitMessage;
}
this.isMakingRequest = true; this.isMakingRequest = true;
this.service this.service
.merge(options) .merge(options)

View File

@ -66,6 +66,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute @total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
@total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute @total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
finder_params[:use_cte] = Feature.enabled?(:use_cte_for_projects_finder, default_enabled: true)
projects = ProjectsFinder projects = ProjectsFinder
.new(params: finder_params, current_user: current_user) .new(params: finder_params, current_user: current_user)
.execute .execute

View File

@ -44,6 +44,8 @@ class ProjectsFinder < UnionFinder
init_collection init_collection
end end
use_cte = params.delete(:use_cte)
collection = Project.wrap_authorized_projects_with_cte(collection) if use_cte
collection = filter_projects(collection) collection = filter_projects(collection)
sort(collection) sort(collection)
end end
@ -177,7 +179,7 @@ class ProjectsFinder < UnionFinder
end end
def sort(items) def sort(items)
params[:sort].present? ? items.sort_by_attribute(params[:sort]) : items.order_id_desc params[:sort].present? ? items.sort_by_attribute(params[:sort]) : items.projects_order_id_desc
end end
def by_archived(projects) def by_archived(projects)

View File

@ -33,7 +33,6 @@ module EnvironmentsHelper
"dashboard-endpoint" => metrics_dashboard_project_environment_path(project, environment, format: :json), "dashboard-endpoint" => metrics_dashboard_project_environment_path(project, environment, format: :json),
"deployments-endpoint" => project_environment_deployments_path(project, environment, format: :json), "deployments-endpoint" => project_environment_deployments_path(project, environment, format: :json),
"default-branch" => project.default_branch, "default-branch" => project.default_branch,
"environments-endpoint": project_environments_path(project, format: :json),
"project-path" => project_path(project), "project-path" => project_path(project),
"tags-path" => project_tags_path(project), "tags-path" => project_tags_path(project),
"has-metrics" => "#{environment.has_metrics?}", "has-metrics" => "#{environment.has_metrics?}",

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class AbuseReportMailer < BaseMailer class AbuseReportMailer < ApplicationMailer
layout 'empty_mailer' layout 'empty_mailer'
helper EmailsHelper helper EmailsHelper

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class BaseMailer < ActionMailer::Base class ApplicationMailer < ActionMailer::Base
around_action :render_with_default_locale around_action :render_with_default_locale
helper ApplicationHelper helper ApplicationHelper

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class EmailRejectionMailer < BaseMailer class EmailRejectionMailer < ApplicationMailer
layout 'empty_mailer' layout 'empty_mailer'
helper EmailsHelper helper EmailsHelper

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class Notify < BaseMailer class Notify < ApplicationMailer
include ActionDispatch::Routing::PolymorphicRoutes include ActionDispatch::Routing::PolymorphicRoutes
include GitlabRoutingHelper include GitlabRoutingHelper
include EmailsHelper include EmailsHelper

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class RepositoryCheckMailer < BaseMailer class RepositoryCheckMailer < ApplicationMailer
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
layout 'empty_mailer' layout 'empty_mailer'

View File

@ -142,7 +142,7 @@ class ApplicationSetting < ApplicationRecord
if: :auto_devops_enabled? if: :auto_devops_enabled?
validates :enabled_git_access_protocol, validates :enabled_git_access_protocol,
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true } inclusion: { in: %w(ssh http), allow_blank: true }
validates :domain_blacklist, validates :domain_blacklist,
presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' }, presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },

View File

@ -16,7 +16,7 @@ module Clusters
include ::Gitlab::Utils::StrongMemoize include ::Gitlab::Utils::StrongMemoize
include IgnorableColumns include IgnorableColumns
ignore_column :kibana_hostname, remove_with: '12.8', remove_after: '2020-01-22' ignore_column :kibana_hostname, remove_with: '12.9', remove_after: '2020-02-22'
default_value_for :version, VERSION default_value_for :version, VERSION

View File

@ -237,8 +237,7 @@ module RelativePositioning
relation relation
.pluck(self.class.relative_positioning_parent_column, Arel.sql("#{calculation}(relative_position) AS position")) .pluck(self.class.relative_positioning_parent_column, Arel.sql("#{calculation}(relative_position) AS position"))
.first&. .first&.last
last
end end
def scoped_items def scoped_items

View File

@ -63,7 +63,7 @@ module ResolvableDiscussion
return unless resolved? return unless resolved?
strong_memoize(:last_resolved_note) do strong_memoize(:last_resolved_note) do
resolved_notes.sort_by(&:resolved_at).last resolved_notes.max_by(&:resolved_at)
end end
end end

View File

@ -397,6 +397,8 @@ class Project < ApplicationRecord
scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) } scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) }
scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) } scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) }
scope :sorted_by_name_asc_limited, ->(limit) { reorder(name: :asc).limit(limit) } scope :sorted_by_name_asc_limited, ->(limit) { reorder(name: :asc).limit(limit) }
# Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name
scope :projects_order_id_desc, -> { reorder("#{table_name}.id DESC") }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) } scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
@ -543,6 +545,11 @@ class Project < ApplicationRecord
) )
end end
def self.wrap_authorized_projects_with_cte(collection)
cte = Gitlab::SQL::CTE.new(:authorized_projects, collection)
Project.with(cte.to_arel).from(cte.alias_to(Project.arel_table))
end
scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') }
scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) }

View File

@ -7,7 +7,7 @@ module Uploads
attr_reader :logger attr_reader :logger
def initialize(logger: nil) def initialize(logger: nil)
@logger ||= Rails.logger # rubocop:disable Gitlab/RailsLogger @logger = Rails.logger # rubocop:disable Gitlab/RailsLogger
end end
def delete_keys_async(keys_to_delete) def delete_keys_async(keys_to_delete)

View File

@ -29,7 +29,7 @@
pre_installed_knative: @cluster.knative_pre_installed? ? 'true': 'false', pre_installed_knative: @cluster.knative_pre_installed? ? 'true': 'false',
help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'), help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-endpoint'), ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-endpoint'),
ingress_dns_help_path: help_page_path('user/project/clusters/index.md', anchor: 'manually-determining-the-external-endpoint'), ingress_dns_help_path: help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint'),
ingress_mod_security_help_path: help_page_path('user/clusters/applications.md', anchor: 'web-application-firewall-modsecurity'), ingress_mod_security_help_path: help_page_path('user/clusters/applications.md', anchor: 'web-application-firewall-modsecurity'),
environments_help_path: help_page_path('ci/environments', anchor: 'defining-environments'), environments_help_path: help_page_path('ci/environments', anchor: 'defining-environments'),
clusters_help_path: help_page_path('user/project/clusters/index.md', anchor: 'deploying-to-a-kubernetes-cluster'), clusters_help_path: help_page_path('user/project/clusters/index.md', anchor: 'deploying-to-a-kubernetes-cluster'),

View File

@ -0,0 +1,5 @@
---
title: Remove invalid data from issue_tracker_data table
merge_request:
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix broken link to documentation
merge_request: 23715
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove kibana_hostname column from clusters_applications_elastic_stacks table
merge_request: 23503
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add selective sync support to Geo Nodes API create endpoint
merge_request: 23729
author: Rajendra Kadam
type: added

View File

@ -0,0 +1,5 @@
---
title: Skip squashing with only one commit in a merge request
merge_request: 23744
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Use CTE optimization fence for loading projects in dashboard
merge_request: 23754
author:
type: performance

View File

@ -46,7 +46,7 @@ module RspecProfilingExt
rescue => err rescue => err
return if @already_logged_example_finished_error # rubocop:disable Gitlab/ModuleWithInstanceVariables return if @already_logged_example_finished_error # rubocop:disable Gitlab/ModuleWithInstanceVariables
$stderr.puts "rspec_profiling couldn't collect an example: #{err}. Further warnings suppressed." warn "rspec_profiling couldn't collect an example: #{err}. Further warnings suppressed."
@already_logged_example_finished_error = true # rubocop:disable Gitlab/ModuleWithInstanceVariables @already_logged_example_finished_error = true # rubocop:disable Gitlab/ModuleWithInstanceVariables
end end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class DropKibanaColumn < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
remove_column :clusters_applications_elastic_stacks, :kibana_hostname, :string, limit: 255
end
end

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class RemoveInvalidIssueTrackerData < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
sql = "DELETE FROM issue_tracker_data WHERE \
(length(encrypted_issues_url) > 0 AND encrypted_issues_url_iv IS NULL) \
OR (length(encrypted_new_issue_url) > 0 AND encrypted_new_issue_url_iv IS NULL) \
OR (length(encrypted_project_url) > 0 AND encrypted_project_url_iv IS NULL)"
execute(sql)
end
def down
# We need to figure out why migrating data to issue_tracker_data table
# failed and then can recreate the data
end
end

View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_01_24_053531) do ActiveRecord::Schema.define(version: 2020_01_27_090233) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm" enable_extension "pg_trgm"
@ -1150,7 +1150,6 @@ ActiveRecord::Schema.define(version: 2020_01_24_053531) do
t.bigint "cluster_id", null: false t.bigint "cluster_id", null: false
t.integer "status", null: false t.integer "status", null: false
t.string "version", limit: 255, null: false t.string "version", limit: 255, null: false
t.string "kibana_hostname", limit: 255
t.text "status_reason" t.text "status_reason"
t.index ["cluster_id"], name: "index_clusters_applications_elastic_stacks_on_cluster_id", unique: true t.index ["cluster_id"], name: "index_clusters_applications_elastic_stacks_on_cluster_id", unique: true
end end

View File

@ -30,6 +30,10 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" https://primary.example.com/a
| `verification_max_capacity` | integer | no | Control the maximum concurrency of repository verification for this node. Defaults to 100. | | `verification_max_capacity` | integer | no | Control the maximum concurrency of repository verification for this node. Defaults to 100. |
| `container_repositories_max_capacity` | integer | no | Control the maximum concurrency of container repository sync for this node. Defaults to 10. | | `container_repositories_max_capacity` | integer | no | Control the maximum concurrency of container repository sync for this node. Defaults to 10. |
| `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node will replicate blobs in Object Storage. Defaults to false. | | `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node will replicate blobs in Object Storage. Defaults to false. |
| `selective_sync_type` | string | no | Limit syncing to only specific groups or shards. Valid values: `"namespaces"`, `"shards"`, or `null`. |
| `selective_sync_shards` | array | no | The repository storage for the projects synced if `selective_sync_type` == `shards`. |
| `selective_sync_namespace_ids` | array | no | The IDs of groups that should be synced, if `selective_sync_type` == `namespaces`. |
| `minimum_reverification_interval` | integer | no | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified. This has no effect when set on a secondary node. |
Example response: Example response:
@ -45,6 +49,10 @@ Example response:
"files_max_capacity": 10, "files_max_capacity": 10,
"repos_max_capacity": 25, "repos_max_capacity": 25,
"verification_max_capacity": 100, "verification_max_capacity": 100,
"selective_sync_type": "namespaces",
"selective_sync_shards": [],
"selective_sync_namespace_ids": [1, 25],
"minimum_reverification_interval": 7,
"container_repositories_max_capacity": 10, "container_repositories_max_capacity": 10,
"sync_object_storage": false, "sync_object_storage": false,
"clone_protocol": "http", "clone_protocol": "http",

View File

@ -76,14 +76,12 @@ module API
name = params[:name] || params[:context] || 'default' name = params[:name] || params[:context] || 'default'
unless pipeline pipeline ||= user_project.ci_pipelines.create!(
pipeline = user_project.ci_pipelines.create!( source: :external,
source: :external, sha: commit.sha,
sha: commit.sha, ref: ref,
ref: ref, user: current_user,
user: current_user, protected: user_project.protected_for?(ref))
protected: user_project.protected_for?(ref))
end
status = GenericCommitStatus.running_or_pending.find_or_initialize_by( status = GenericCommitStatus.running_or_pending.find_or_initialize_by(
project: user_project, project: user_project,

View File

@ -135,11 +135,11 @@ module Backup
progress.print 'Unpacking backup ... ' progress.print 'Unpacking backup ... '
unless Kernel.system(*%W(tar -xf #{tar_file})) if Kernel.system(*%W(tar -xf #{tar_file}))
progress.puts 'done'.color(:green)
else
progress.puts 'unpacking backup failed'.color(:red) progress.puts 'unpacking backup failed'.color(:red)
exit 1 exit 1
else
progress.puts 'done'.color(:green)
end end
ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0 ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0

View File

@ -15,7 +15,7 @@ module Gitlab
4 => 'blue', 4 => 'blue',
5 => 'magenta', 5 => 'magenta',
6 => 'cyan', 6 => 'cyan',
7 => 'white', # not that this is gray in the dark (aka default) color table 7 => 'white' # not that this is gray in the dark (aka default) color table
}.freeze }.freeze
STYLE_SWITCHES = { STYLE_SWITCHES = {

View File

@ -12,7 +12,7 @@ module Gitlab
@options = { from: 7.days.ago } @options = { from: 7.days.ago }
end end
def to_json def to_json(*)
total = 0 total = 0
values = values =

View File

@ -102,7 +102,7 @@ module Gitlab
def populate! def populate!
return if @populated return if @populated
each { nil } # force a loop through all diffs each {} # force a loop through all diffs
nil nil
end end

View File

@ -16,13 +16,13 @@ module Gitlab
def signature_text def signature_text
strong_memoize(:signature_text) do strong_memoize(:signature_text) do
@signature_data&.itself && @signature_data[0] @signature_data&.itself && @signature_data[0] # rubocop:disable Lint/SafeNavigationConsistency
end end
end end
def signed_text def signed_text
strong_memoize(:signed_text) do strong_memoize(:signed_text) do
@signature_data&.itself && @signature_data[1] @signature_data&.itself && @signature_data[1] # rubocop:disable Lint/SafeNavigationConsistency
end end
end end

View File

@ -32,7 +32,7 @@ module Gitlab
@lexer ||= custom_language || begin @lexer ||= custom_language || begin
Rouge::Lexer.guess(filename: @blob_name, source: @blob_content).new Rouge::Lexer.guess(filename: @blob_name, source: @blob_content).new
rescue Rouge::Guesser::Ambiguous => e rescue Rouge::Guesser::Ambiguous => e
e.alternatives.sort_by(&:tag).first e.alternatives.min_by(&:tag)
end end
end end

View File

@ -106,10 +106,10 @@ module Gitlab
@wiki_blobs ||= begin @wiki_blobs ||= begin
if project.wiki_enabled? && query.present? if project.wiki_enabled? && query.present?
unless project.wiki.empty? if project.wiki.empty?
Gitlab::WikiFileFinder.new(project, repository_wiki_ref).find(query)
else
[] []
else
Gitlab::WikiFileFinder.new(project, repository_wiki_ref).find(query)
end end
else else
[] []

View File

@ -32,7 +32,7 @@ module Gitlab
private private
def move(path_was, path, base_dir = nil) def move(path_was, path, base_dir = nil)
base_dir = root_dir unless base_dir base_dir ||= root_dir
from = File.join(base_dir, path_was) from = File.join(base_dir, path_was)
to = File.join(base_dir, path) to = File.join(base_dir, path)
FileUtils.mv(from, to) FileUtils.mv(from, to)

View File

@ -33,7 +33,7 @@ module Gitlab
self self
end end
def to_json def to_json(*)
{ key: key, name: name, content: content } { key: key, name: name, content: content }
end end

View File

@ -57,11 +57,7 @@ module SystemCheck
end end
def should_sanitize? def should_sanitize?
if ENV['SANITIZE'] == 'true' ENV['SANITIZE'] == 'true'
true
else
false
end
end end
def omnibus_gitlab? def omnibus_gitlab?

View File

@ -1,3 +1,4 @@
# frozen_string_literal: true
namespace :yarn do namespace :yarn do
desc 'Ensure Yarn is installed' desc 'Ensure Yarn is installed'

View File

@ -22014,9 +22014,6 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}" msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr "" msgstr ""
msgid "ciReport|%{namespace} is affected by %{vulnerability}."
msgstr ""
msgid "ciReport|%{remainingPackagesCount} more" msgid "ciReport|%{remainingPackagesCount} more"
msgstr "" msgstr ""
@ -22075,9 +22072,6 @@ msgstr ""
msgid "ciReport|%{reportType}: Loading resulted in an error" msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr "" msgstr ""
msgid "ciReport|%{vulnerability} in %{featurename}"
msgstr ""
msgid "ciReport|(errors when loading results)" msgid "ciReport|(errors when loading results)"
msgstr "" msgstr ""
@ -22234,15 +22228,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again." msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "" msgstr ""
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
msgid "ciReport|Upgrade %{name} to %{fixed}."
msgstr ""
msgid "ciReport|Upgrade to %{fixed}."
msgstr ""
msgid "ciReport|Used by %{packagesString}" msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}" msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
msgstr[0] "" msgstr[0] ""

View File

@ -111,7 +111,6 @@
"raw-loader": "^3.1.0", "raw-loader": "^3.1.0",
"sanitize-html": "^1.20.0", "sanitize-html": "^1.20.0",
"select2": "3.5.2-browserify", "select2": "3.5.2-browserify",
"sha1": "^1.1.1",
"smooshpack": "^0.0.54", "smooshpack": "^0.0.54",
"sortablejs": "^1.10.0", "sortablejs": "^1.10.0",
"sql.js": "^0.4.0", "sql.js": "^0.4.0",

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
$: << File.expand_path(File.dirname(__FILE__)) $: << File.expand_path(__dir__)
Encoding.default_external = 'UTF-8' Encoding.default_external = 'UTF-8'

View File

@ -3,7 +3,7 @@
require 'digest/sha1' require 'digest/sha1'
module QA module QA
context 'Release', :docker, quarantine: 'https://gitlab.com/gitlab-org/gitlab/issues/196047' do context 'Release', :docker do
describe 'Git clone using a deploy key' do describe 'Git clone using a deploy key' do
before do before do
Flow::Login.sign_in Flow::Login.sign_in

View File

@ -134,7 +134,7 @@ describe 'Admin Groups' do
end end
describe 'add user into a group', :js do describe 'add user into a group', :js do
shared_context 'adds user into a group' do shared_examples 'adds user into a group' do
it do it do
visit admin_group_path(group) visit admin_group_path(group)

View File

@ -6,6 +6,7 @@ describe 'User squashes a merge request', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:source_branch) { 'csv' } let(:source_branch) { 'csv' }
let(:protected_source_branch) { false }
let!(:original_head) { project.repository.commit('master') } let!(:original_head) { project.repository.commit('master') }
@ -40,7 +41,7 @@ describe 'User squashes a merge request', :js do
def accept_mr def accept_mr
expect(page).to have_button('Merge') expect(page).to have_button('Merge')
uncheck 'Delete source branch' uncheck 'Delete source branch' unless protected_source_branch
click_on 'Merge' click_on 'Merge'
end end
@ -56,14 +57,34 @@ describe 'User squashes a merge request', :js do
end end
context 'when the MR has only one commit' do context 'when the MR has only one commit' do
let(:source_branch) { 'master' }
let(:target_branch) { 'branch-merged' }
let(:protected_source_branch) { true }
let(:source_sha) { project.commit(source_branch).sha }
let(:target_sha) { project.commit(target_branch).sha }
before do before do
merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: 'master', target_branch: 'branch-merged') merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: source_branch, target_branch: target_branch, squash: true)
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
end end
it 'does not show the squash checkbox' do it 'accepts the merge request without issuing a squash request', :sidekiq_inline do
expect_next_instance_of(Gitlab::GitalyClient::OperationService) do |instance|
expect(instance).not_to receive(:user_squash)
end
expect(project.repository.ancestor?(source_branch, target_branch)).to be_falsey
expect(page).not_to have_field('squash') expect(page).not_to have_field('squash')
accept_mr
expect(page).to have_content('Merged')
latest_target_commits = project.repository.commits_between(source_sha, target_sha).map(&:raw)
expect(latest_target_commits.count).to eq(1)
expect(project.repository.ancestor?(source_branch, target_branch)).to be_truthy
end end
end end

View File

@ -28,210 +28,227 @@ describe ProjectsFinder, :do_not_mock_admin_mode do
let(:params) { {} } let(:params) { {} }
let(:current_user) { user } let(:current_user) { user }
let(:project_ids_relation) { nil } let(:project_ids_relation) { nil }
let(:finder) { described_class.new(params: params, current_user: current_user, project_ids_relation: project_ids_relation) } let(:use_cte) { true }
let(:finder) { described_class.new(params: params.merge(use_cte: use_cte), current_user: current_user, project_ids_relation: project_ids_relation) }
subject { finder.execute } subject { finder.execute }
describe 'without a user' do shared_examples 'ProjectFinder#execute examples' do
let(:current_user) { nil } describe 'without a user' do
let(:current_user) { nil }
it { is_expected.to eq([public_project]) } it { is_expected.to eq([public_project]) }
end
describe 'with a user' do
describe 'without private projects' do
it { is_expected.to match_array([public_project, internal_project]) }
end end
describe 'with private projects' do describe 'with a user' do
describe 'without private projects' do
it { is_expected.to match_array([public_project, internal_project]) }
end
describe 'with private projects' do
before do
private_project.add_maintainer(user)
end
it { is_expected.to match_array([public_project, internal_project, private_project]) }
end
end
describe 'with project_ids_relation' do
let(:project_ids_relation) { Project.where(id: internal_project.id) }
it { is_expected.to eq([internal_project]) }
end
describe 'with id_after' do
context 'only returns projects with a project id greater than given' do
let(:params) { { id_after: internal_project.id }}
it { is_expected.to eq([public_project]) }
end
end
describe 'with id_before' do
context 'only returns projects with a project id less than given' do
let(:params) { { id_before: public_project.id }}
it { is_expected.to eq([internal_project]) }
end
end
describe 'with both id_before and id_after' do
context 'only returns projects with a project id less than given' do
let!(:projects) { create_list(:project, 5, :public) }
let(:params) { { id_after: projects.first.id, id_before: projects.last.id }}
it { is_expected.to contain_exactly(*projects[1..-2]) }
end
end
describe 'filter by visibility_level' do
before do before do
private_project.add_maintainer(user) private_project.add_maintainer(user)
end end
it { is_expected.to match_array([public_project, internal_project, private_project]) } context 'private' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::PRIVATE } }
it { is_expected.to eq([private_project]) }
end
context 'internal' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::INTERNAL } }
it { is_expected.to eq([internal_project]) }
end
context 'public' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::PUBLIC } }
it { is_expected.to eq([public_project]) }
end
end end
end
describe 'with project_ids_relation' do describe 'filter by tags' do
let(:project_ids_relation) { Project.where(id: internal_project.id) } before do
public_project.tag_list.add('foo')
public_project.save!
end
it { is_expected.to eq([internal_project]) } let(:params) { { tag: 'foo' } }
end
describe 'with id_after' do
context 'only returns projects with a project id greater than given' do
let(:params) { { id_after: internal_project.id }}
it { is_expected.to eq([public_project]) } it { is_expected.to eq([public_project]) }
end end
end
describe 'with id_before' do describe 'filter by personal' do
context 'only returns projects with a project id less than given' do let!(:personal_project) { create(:project, namespace: user.namespace) }
let(:params) { { id_before: public_project.id }} let(:params) { { personal: true } }
it { is_expected.to eq([internal_project]) } it { is_expected.to eq([personal_project]) }
end
end
describe 'with both id_before and id_after' do
context 'only returns projects with a project id less than given' do
let!(:projects) { create_list(:project, 5, :public) }
let(:params) { { id_after: projects.first.id, id_before: projects.last.id }}
it { is_expected.to contain_exactly(*projects[1..-2]) }
end
end
describe 'filter by visibility_level' do
before do
private_project.add_maintainer(user)
end end
context 'private' do describe 'filter by search' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::PRIVATE } } let(:params) { { search: 'C' } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by name for backward compatibility' do
let(:params) { { name: 'C' } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by archived' do
let!(:archived_project) { create(:project, :public, :archived, name: 'E', path: 'E') }
context 'non_archived=true' do
let(:params) { { non_archived: true } }
it { is_expected.to match_array([public_project, internal_project]) }
end
context 'non_archived=false' do
let(:params) { { non_archived: false } }
it { is_expected.to match_array([public_project, internal_project, archived_project]) }
end
describe 'filter by archived only' do
let(:params) { { archived: 'only' } }
it { is_expected.to eq([archived_project]) }
end
describe 'filter by archived for backward compatibility' do
let(:params) { { archived: false } }
it { is_expected.to match_array([public_project, internal_project]) }
end
end
describe 'filter by trending' do
let!(:trending_project) { create(:trending_project, project: public_project) }
let(:params) { { trending: true } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by owned' do
let(:params) { { owned: true } }
let!(:owned_project) { create(:project, :private, namespace: current_user.namespace) }
it { is_expected.to eq([owned_project]) }
end
describe 'filter by non_public' do
let(:params) { { non_public: true } }
before do
private_project.add_developer(current_user)
end
it { is_expected.to eq([private_project]) } it { is_expected.to eq([private_project]) }
end end
context 'internal' do describe 'filter by starred' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::INTERNAL } } let(:params) { { starred: true } }
it { is_expected.to eq([internal_project]) }
end
context 'public' do
let(:params) { { visibility_level: Gitlab::VisibilityLevel::PUBLIC } }
it { is_expected.to eq([public_project]) }
end
end
describe 'filter by tags' do
before do
public_project.tag_list.add('foo')
public_project.save!
end
let(:params) { { tag: 'foo' } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by personal' do
let!(:personal_project) { create(:project, namespace: user.namespace) }
let(:params) { { personal: true } }
it { is_expected.to eq([personal_project]) }
end
describe 'filter by search' do
let(:params) { { search: 'C' } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by name for backward compatibility' do
let(:params) { { name: 'C' } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by archived' do
let!(:archived_project) { create(:project, :public, :archived, name: 'E', path: 'E') }
context 'non_archived=true' do
let(:params) { { non_archived: true } }
it { is_expected.to match_array([public_project, internal_project]) }
end
context 'non_archived=false' do
let(:params) { { non_archived: false } }
it { is_expected.to match_array([public_project, internal_project, archived_project]) }
end
describe 'filter by archived only' do
let(:params) { { archived: 'only' } }
it { is_expected.to eq([archived_project]) }
end
describe 'filter by archived for backward compatibility' do
let(:params) { { archived: false } }
it { is_expected.to match_array([public_project, internal_project]) }
end
end
describe 'filter by trending' do
let!(:trending_project) { create(:trending_project, project: public_project) }
let(:params) { { trending: true } }
it { is_expected.to eq([public_project]) }
end
describe 'filter by owned' do
let(:params) { { owned: true } }
let!(:owned_project) { create(:project, :private, namespace: current_user.namespace) }
it { is_expected.to eq([owned_project]) }
end
describe 'filter by non_public' do
let(:params) { { non_public: true } }
before do
private_project.add_developer(current_user)
end
it { is_expected.to eq([private_project]) }
end
describe 'filter by starred' do
let(:params) { { starred: true } }
before do
current_user.toggle_star(public_project)
end
it { is_expected.to eq([public_project]) }
it 'returns only projects the user has access to' do
current_user.toggle_star(private_project)
is_expected.to eq([public_project])
end
end
describe 'filter by without_deleted' do
let(:params) { { without_deleted: true } }
let!(:pending_delete_project) { create(:project, :public, pending_delete: true) }
it { is_expected.to match_array([public_project, internal_project]) }
end
describe 'sorting' do
let(:params) { { sort: 'name_asc' } }
it { is_expected.to eq([internal_project, public_project]) }
end
describe 'with admin user' do
let(:user) { create(:admin) }
context 'admin mode enabled' do
before do before do
enable_admin_mode!(current_user) current_user.toggle_star(public_project)
end end
it { is_expected.to match_array([public_project, internal_project, private_project, shared_project]) } it { is_expected.to eq([public_project]) }
it 'returns only projects the user has access to' do
current_user.toggle_star(private_project)
is_expected.to eq([public_project])
expect(subject.count).to eq(1)
expect(subject.limit(1000).count).to eq(1)
end
end end
context 'admin mode disabled' do describe 'filter by without_deleted' do
let(:params) { { without_deleted: true } }
let!(:pending_delete_project) { create(:project, :public, pending_delete: true) }
it { is_expected.to match_array([public_project, internal_project]) } it { is_expected.to match_array([public_project, internal_project]) }
end end
describe 'sorting' do
let(:params) { { sort: 'name_asc' } }
it { is_expected.to eq([internal_project, public_project]) }
end
describe 'with admin user' do
let(:user) { create(:admin) }
context 'admin mode enabled' do
before do
enable_admin_mode!(current_user)
end
it { is_expected.to match_array([public_project, internal_project, private_project, shared_project]) }
end
context 'admin mode disabled' do
it { is_expected.to match_array([public_project, internal_project]) }
end
end
end
describe 'without CTE flag enabled' do
let(:use_cte) { false }
it_behaves_like 'ProjectFinder#execute examples'
end
describe 'with CTE flag enabled' do
let(:use_cte) { true }
it_behaves_like 'ProjectFinder#execute examples'
end end
end end
end end

View File

@ -23,7 +23,6 @@ export const propsData = {
emptyNoDataSvgPath: '/path/to/no-data.svg', emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg', emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg', emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/-/environments.json',
currentEnvironmentName: 'production', currentEnvironmentName: 'production',
customMetricsAvailable: false, customMetricsAvailable: false,
customMetricsPath: '', customMetricsPath: '',

View File

@ -159,7 +159,6 @@ describe('Monitoring store actions', () => {
{ {
metricsEndpoint: 'additional_metrics.json', metricsEndpoint: 'additional_metrics.json',
deploymentsEndpoint: 'deployments.json', deploymentsEndpoint: 'deployments.json',
environmentsEndpoint: 'deployments.json',
}, },
mockedState, mockedState,
[ [
@ -168,7 +167,6 @@ describe('Monitoring store actions', () => {
payload: { payload: {
metricsEndpoint: 'additional_metrics.json', metricsEndpoint: 'additional_metrics.json',
deploymentsEndpoint: 'deployments.json', deploymentsEndpoint: 'deployments.json',
environmentsEndpoint: 'deployments.json',
}, },
}, },
], ],

View File

@ -81,13 +81,11 @@ describe('Monitoring mutations', () => {
it('should set all the endpoints', () => { it('should set all the endpoints', () => {
mutations[types.SET_ENDPOINTS](stateCopy, { mutations[types.SET_ENDPOINTS](stateCopy, {
metricsEndpoint: 'additional_metrics.json', metricsEndpoint: 'additional_metrics.json',
environmentsEndpoint: 'environments.json',
deploymentsEndpoint: 'deployments.json', deploymentsEndpoint: 'deployments.json',
dashboardEndpoint: 'dashboard.json', dashboardEndpoint: 'dashboard.json',
projectPath: '/gitlab-org/gitlab-foss', projectPath: '/gitlab-org/gitlab-foss',
}); });
expect(stateCopy.metricsEndpoint).toEqual('additional_metrics.json'); expect(stateCopy.metricsEndpoint).toEqual('additional_metrics.json');
expect(stateCopy.environmentsEndpoint).toEqual('environments.json');
expect(stateCopy.deploymentsEndpoint).toEqual('deployments.json'); expect(stateCopy.deploymentsEndpoint).toEqual('deployments.json');
expect(stateCopy.dashboardEndpoint).toEqual('dashboard.json'); expect(stateCopy.dashboardEndpoint).toEqual('dashboard.json');
expect(stateCopy.projectPath).toEqual('/gitlab-org/gitlab-foss'); expect(stateCopy.projectPath).toEqual('/gitlab-org/gitlab-foss');

View File

@ -29,7 +29,6 @@ describe EnvironmentsHelper do
'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json), 'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json), 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json),
'default-branch' => 'master', 'default-branch' => 'master',
'environments-endpoint': project_environments_path(project, format: :json),
'project-path' => project_path(project), 'project-path' => project_path(project),
'tags-path' => project_tags_path(project), 'tags-path' => project_tags_path(project),
'has-metrics' => "#{environment.has_metrics?}", 'has-metrics' => "#{environment.has_metrics?}",

View File

@ -30,7 +30,6 @@ const propsData = {
emptyNoDataSvgPath: '/path/to/no-data.svg', emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg', emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg', emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
currentEnvironmentName: 'production', currentEnvironmentName: 'production',
customMetricsAvailable: false, customMetricsAvailable: false,
customMetricsPath: '', customMetricsPath: '',

View File

@ -62,7 +62,7 @@ describe Gitlab::Metrics::Dashboard::Processor do
'metric_a1', # group priority 1, panel weight 1 'metric_a1', # group priority 1, panel weight 1
project_business_metric.id, # group priority 0, panel weight nil (0) project_business_metric.id, # group priority 0, panel weight nil (0)
project_response_metric.id, # group priority -5, panel weight nil (0) project_response_metric.id, # group priority -5, panel weight nil (0)
project_system_metric.id, # group priority -10, panel weight nil (0) project_system_metric.id # group priority -10, panel weight nil (0)
] ]
actual_metrics_order = all_metrics.map { |m| m[:id] || m[:metric_id] } actual_metrics_order = all_metrics.map { |m| m[:id] || m[:metric_id] }

View File

@ -18,7 +18,7 @@ describe 'Marginalia spec' do
end end
end end
class MarginaliaTestMailer < BaseMailer class MarginaliaTestMailer < ApplicationMailer
def first_user def first_user
User.first User.first
end end

View File

@ -0,0 +1,59 @@
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200127090233_remove_invalid_issue_tracker_data.rb')
describe RemoveInvalidIssueTrackerData, :migration do
let(:issue_tracker_data) { table(:issue_tracker_data) }
let(:services) { table(:services) }
let(:service) { services.create(id: 1) }
let(:data) do
{
service_id: service.id,
encrypted_issues_url: 'http:url.com',
encrypted_issues_url_iv: 'somevalue',
encrypted_new_issue_url: 'http:url.com',
encrypted_new_issue_url_iv: 'somevalue',
encrypted_project_url: 'username',
encrypted_project_url_iv: 'somevalue'
}
end
let!(:valid_data) { issue_tracker_data.create(data) }
let!(:empty_data) { issue_tracker_data.create(service_id: service.id) }
let!(:invalid_issues_url) do
data[:encrypted_issues_url_iv] = nil
issue_tracker_data.create(data)
end
let!(:missing_issues_url) do
data[:encrypted_issues_url] = ''
data[:encrypted_issues_url_iv] = nil
issue_tracker_data.create(data)
end
let!(:invalid_new_isue_url) do
data[:encrypted_new_issue_url_iv] = nil
issue_tracker_data.create(data)
end
let!(:missing_new_issue_url) do
data[:encrypted_new_issue_url] = ''
issue_tracker_data.create(data)
end
let!(:invalid_project_url) do
data[:encrypted_project_url_iv] = nil
issue_tracker_data.create(data)
end
let!(:missing_project_url) do
data[:encrypted_project_url] = nil
data[:encrypted_project_url_iv] = nil
issue_tracker_data.create(data)
end
it 'removes the invalid data' do
valid_data_records = [valid_data, empty_data, missing_issues_url, missing_new_issue_url, missing_project_url]
expect { migrate! }.to change { issue_tracker_data.count }.from(8).to(5)
expect(issue_tracker_data.all).to match_array(valid_data_records)
end
end

View File

@ -3780,6 +3780,25 @@ describe Project do
end end
end end
describe '.wrap_authorized_projects_with_cte' do
let!(:user) { create(:user) }
let!(:private_project) do
create(:project, :private, creator: user, namespace: user.namespace)
end
let!(:public_project) { create(:project, :public) }
let(:projects) { described_class.all.public_or_visible_to_user(user) }
subject { described_class.wrap_authorized_projects_with_cte(projects) }
it 'wrapped query matches original' do
expect(subject.to_sql).to match(/^WITH "authorized_projects" AS/)
expect(subject).to match_array(projects)
end
end
describe '#pages_available?' do describe '#pages_available?' do
let(:project) { create(:project, group: group) } let(:project) { create(:project, group: group) }

View File

@ -11,10 +11,8 @@ describe MergeRequests::CreateFromIssueService do
let(:milestone_id) { create(:milestone, project: project).id } let(:milestone_id) { create(:milestone, project: project).id }
let(:issue) { create(:issue, project: project, milestone_id: milestone_id) } let(:issue) { create(:issue, project: project, milestone_id: milestone_id) }
let(:custom_source_branch) { 'custom-source-branch' } let(:custom_source_branch) { 'custom-source-branch' }
let(:service) { described_class.new(project, user, service_params) }
subject(:service) { described_class.new(project, user, service_params) } let(:service_with_custom_source_branch) { described_class.new(project, user, branch_name: custom_source_branch, **service_params) }
subject(:service_with_custom_source_branch) { described_class.new(project, user, branch_name: custom_source_branch, **service_params) }
before do before do
project.add_developer(user) project.add_developer(user)

View File

@ -2501,7 +2501,7 @@ chardet@^0.5.0:
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029"
integrity sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g== integrity sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==
"charenc@>= 0.0.1", charenc@~0.0.1: charenc@~0.0.1:
version "0.0.2" version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
@ -3114,7 +3114,7 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0" shebang-command "^1.2.0"
which "^1.2.9" which "^1.2.9"
"crypt@>= 0.0.1", crypt@~0.0.1: crypt@~0.0.1:
version "0.0.2" version "0.0.2"
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
@ -10136,14 +10136,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
inherits "^2.0.1" inherits "^2.0.1"
safe-buffer "^5.0.1" safe-buffer "^5.0.1"
sha1@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848"
integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=
dependencies:
charenc ">= 0.0.1"
crypt ">= 0.0.1"
shallow-clone@^3.0.0: shallow-clone@^3.0.0:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"