Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
e06d0e7796
commit
951616a26a
|
@ -164,24 +164,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Temporary hack until `gitlab-ui` issue is fixed.
|
||||
// https://gitlab.com/gitlab-org/gitlab-ui/issues/164
|
||||
.gl-dropdown .dropdown-menu-toggle {
|
||||
.gl-dropdown-caret {
|
||||
position: absolute;
|
||||
right: $gl-padding-8;
|
||||
top: $gl-padding-8;
|
||||
}
|
||||
padding-right: $gl-padding-8;
|
||||
|
||||
// Add some child to the button so that the default height kicks in
|
||||
// when there's no text (since the caret is now aboslute)
|
||||
&::after {
|
||||
border: 0;
|
||||
content: ' ';
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
.gl-dropdown-toggle-text {
|
||||
min-height: $gl-line-height-20;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class Admin::Serverless::DomainsController < Admin::ApplicationController
|
||||
before_action :check_feature_flag
|
||||
before_action :domain, only: [:update, :verify]
|
||||
before_action :domain, only: [:update, :verify, :destroy]
|
||||
|
||||
def index
|
||||
@domain = PagesDomain.instance_serverless.first_or_initialize
|
||||
|
@ -30,6 +30,20 @@ class Admin::Serverless::DomainsController < Admin::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
if domain.serverless_domain_clusters.count > 0
|
||||
return redirect_to admin_serverless_domains_path,
|
||||
status: :conflict,
|
||||
notice: _('Domain cannot be deleted while associated to one or more clusters.')
|
||||
end
|
||||
|
||||
domain.destroy!
|
||||
|
||||
redirect_to admin_serverless_domains_path,
|
||||
status: :found,
|
||||
notice: _('Domain was successfully deleted.')
|
||||
end
|
||||
|
||||
def verify
|
||||
result = VerifyPagesDomainService.new(domain).execute
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ class PagesDomain < ApplicationRecord
|
|||
|
||||
belongs_to :project
|
||||
has_many :acme_orders, class_name: "PagesDomainAcmeOrder"
|
||||
has_many :serverless_domain_clusters, class_name: 'Serverless::DomainCluster', inverse_of: :pages_domain
|
||||
|
||||
validates :domain, hostname: { allow_numeric_hostname: true }
|
||||
validates :domain, uniqueness: { case_sensitive: false }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add version column to operations_feature_flags table
|
||||
merge_request: 25552
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# https://gitlab.com/gitlab-org/gitlab/issues/207937
|
||||
# http-cookie is not thread-safe while loading it the first time, see:
|
||||
# https://github.com/sparklemotion/http-cookie/issues/6#issuecomment-543570876
|
||||
# If we're using it, we should eagerly load it.
|
||||
# For now, we have an implicit dependency on it via:
|
||||
# * http
|
||||
# * rest-client
|
||||
require 'http/cookie_jar/hash_store' if Gem.loaded_specs.key?('http-cookie')
|
|
@ -33,7 +33,7 @@ namespace :admin do
|
|||
resources :gitaly_servers, only: [:index]
|
||||
|
||||
namespace :serverless do
|
||||
resources :domains, only: [:index, :create, :update] do
|
||||
resources :domains, only: [:index, :create, :update, :destroy] do
|
||||
member do
|
||||
post '/verify', to: 'domains#verify'
|
||||
end
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddVersionToFeatureFlagsTable < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
FEATURE_FLAG_LEGACY_VERSION = 1
|
||||
|
||||
def up
|
||||
# The operations_feature_flags table is small enough that we can disable this cop.
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25552#note_291202882
|
||||
# rubocop: disable Migration/AddColumnWithDefault
|
||||
add_column_with_default(:operations_feature_flags, :version, :smallint, default: FEATURE_FLAG_LEGACY_VERSION, allow_null: false)
|
||||
# rubocop: enable Migration/AddColumnWithDefault
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column(:operations_feature_flags, :version)
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2020_02_21_144534) do
|
||||
ActiveRecord::Schema.define(version: 2020_02_24_163804) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_trgm"
|
||||
|
@ -2916,6 +2916,7 @@ ActiveRecord::Schema.define(version: 2020_02_21_144534) do
|
|||
t.string "name", null: false
|
||||
t.text "description"
|
||||
t.integer "iid", null: false
|
||||
t.integer "version", limit: 2, default: 1, null: false
|
||||
t.index ["project_id", "iid"], name: "index_operations_feature_flags_on_project_id_and_iid", unique: true
|
||||
t.index ["project_id", "name"], name: "index_operations_feature_flags_on_project_id_and_name", unique: true
|
||||
end
|
||||
|
|
|
@ -165,7 +165,9 @@ module Gitlab
|
|||
end
|
||||
|
||||
def truncated?
|
||||
size && (size > loaded_size)
|
||||
return false unless size && loaded_size
|
||||
|
||||
size > loaded_size
|
||||
end
|
||||
|
||||
# Valid LFS object pointer is a text file consisting of
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module ImportExport
|
||||
module AfterExportStrategies
|
||||
class MoveFileStrategy < BaseAfterExportStrategy
|
||||
def initialize(archive_path:)
|
||||
@archive_path = archive_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def strategy_execute
|
||||
FileUtils.mv(project.export_file.path, @archive_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
module Gitlab
|
||||
module Profiler
|
||||
extend WithRequestStore
|
||||
|
||||
FILTERED_STRING = '[FILTERED]'
|
||||
|
||||
IGNORE_BACKTRACES = %w[
|
||||
|
@ -58,28 +60,26 @@ module Gitlab
|
|||
|
||||
logger = create_custom_logger(logger, private_token: private_token)
|
||||
|
||||
RequestStore.begin!
|
||||
result = with_request_store do
|
||||
# Make an initial call for an asset path in development mode to avoid
|
||||
# sprockets dominating the profiler output.
|
||||
ActionController::Base.helpers.asset_path('katex.css') if Rails.env.development?
|
||||
|
||||
# Make an initial call for an asset path in development mode to avoid
|
||||
# sprockets dominating the profiler output.
|
||||
ActionController::Base.helpers.asset_path('katex.css') if Rails.env.development?
|
||||
# Rails loads internationalization files lazily the first time a
|
||||
# translation is needed. Running this prevents this overhead from showing
|
||||
# up in profiles.
|
||||
::I18n.t('.')[:test_string]
|
||||
|
||||
# Rails loads internationalization files lazily the first time a
|
||||
# translation is needed. Running this prevents this overhead from showing
|
||||
# up in profiles.
|
||||
::I18n.t('.')[:test_string]
|
||||
# Remove API route mounting from the profile.
|
||||
app.get('/api/v4/users')
|
||||
|
||||
# Remove API route mounting from the profile.
|
||||
app.get('/api/v4/users')
|
||||
|
||||
result = with_custom_logger(logger) do
|
||||
with_user(user) do
|
||||
RubyProf.profile { app.public_send(verb, url, params: post_data, headers: headers) } # rubocop:disable GitlabSecurity/PublicSend
|
||||
with_custom_logger(logger) do
|
||||
with_user(user) do
|
||||
RubyProf.profile { app.public_send(verb, url, params: post_data, headers: headers) } # rubocop:disable GitlabSecurity/PublicSend
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RequestStore.end!
|
||||
|
||||
log_load_times_by_model(logger)
|
||||
|
||||
result
|
||||
|
|
|
@ -21,7 +21,7 @@ module Gitlab
|
|||
QUERY_OR_OPERATOR = '|'
|
||||
QUERY_AND_OPERATOR = '&'
|
||||
QUERY_CONCATENATE_OPERATOR = ','
|
||||
QUERY_TERM_REGEX = %r{^(\w+)(!?=)([\w#{QUERY_CONCATENATE_OPERATOR}]+)}.freeze
|
||||
QUERY_TERM_REGEX = %r{^(\w+)(!?=)([\w:#{QUERY_CONCATENATE_OPERATOR}]+)}.freeze
|
||||
|
||||
QUERY_PREDICATES = {
|
||||
feature_category: :to_sym,
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
module Gitlab
|
||||
module SidekiqMiddleware
|
||||
class RequestStoreMiddleware
|
||||
include Gitlab::WithRequestStore
|
||||
|
||||
def call(worker, job, queue)
|
||||
RequestStore.begin!
|
||||
yield
|
||||
ensure
|
||||
RequestStore.end!
|
||||
RequestStore.clear!
|
||||
with_request_store do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'prometheus/pid_provider'
|
||||
|
||||
module Gitlab
|
||||
module Utils
|
||||
class Measuring
|
||||
def initialize(logger: Logger.new($stdout))
|
||||
@logger = logger
|
||||
end
|
||||
|
||||
def with_measuring
|
||||
logger.info "Measuring enabled..."
|
||||
with_gc_counter do
|
||||
with_count_queries do
|
||||
with_measure_time do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
logger.info "Memory usage: #{Gitlab::Metrics::System.memory_usage.to_f / 1024 / 1024} MiB"
|
||||
logger.info "Label: #{::Prometheus::PidProvider.worker_id}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :logger
|
||||
|
||||
def with_count_queries(&block)
|
||||
count = 0
|
||||
|
||||
counter_f = ->(_name, _started, _finished, _unique_id, payload) {
|
||||
count += 1 unless payload[:name].in? %w[CACHE SCHEMA]
|
||||
}
|
||||
|
||||
ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)
|
||||
|
||||
logger.info "Number of sql calls: #{count}"
|
||||
end
|
||||
|
||||
def with_gc_counter
|
||||
gc_counts_before = GC.stat.select { |k, _v| k =~ /count/ }
|
||||
yield
|
||||
gc_counts_after = GC.stat.select { |k, _v| k =~ /count/ }
|
||||
stats = gc_counts_before.merge(gc_counts_after) { |_k, vb, va| va - vb }
|
||||
|
||||
logger.info "Total GC count: #{stats[:count]}"
|
||||
logger.info "Minor GC count: #{stats[:minor_gc_count]}"
|
||||
logger.info "Major GC count: #{stats[:major_gc_count]}"
|
||||
end
|
||||
|
||||
def with_measure_time
|
||||
timing = Benchmark.realtime do
|
||||
yield
|
||||
end
|
||||
|
||||
logger.info "Time to finish: #{duration_in_numbers(timing)}"
|
||||
end
|
||||
|
||||
def duration_in_numbers(duration_in_seconds)
|
||||
seconds = duration_in_seconds % 1.minute
|
||||
minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute)
|
||||
hours = duration_in_seconds / 1.hour
|
||||
|
||||
if hours == 0
|
||||
"%02d:%02d" % [minutes, seconds]
|
||||
else
|
||||
"%02d:%02d:%02d" % [hours, minutes, seconds]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module WithRequestStore
|
||||
def with_request_store
|
||||
RequestStore.begin!
|
||||
yield
|
||||
ensure
|
||||
RequestStore.end!
|
||||
RequestStore.clear!
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,94 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'gitlab/with_request_store'
|
||||
|
||||
# Export project to archive
|
||||
#
|
||||
# @example
|
||||
# bundle exec rake "gitlab:import_export:export[root, root, project_to_export, /path/to/file.tar.gz, true]"
|
||||
#
|
||||
namespace :gitlab do
|
||||
namespace :import_export do
|
||||
desc 'GitLab | Import/Export | EXPERIMENTAL | Export large project archives'
|
||||
task :export, [:username, :namespace_path, :project_path, :archive_path, :measurement_enabled] => :gitlab_environment do |_t, args|
|
||||
# Load it here to avoid polluting Rake tasks with Sidekiq test warnings
|
||||
require 'sidekiq/testing'
|
||||
|
||||
warn_user_is_not_gitlab
|
||||
|
||||
if ENV['IMPORT_DEBUG'].present?
|
||||
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
||||
Gitlab::Metrics::Exporter::SidekiqExporter.instance.start
|
||||
end
|
||||
|
||||
GitlabProjectExport.new(
|
||||
namespace_path: args.namespace_path,
|
||||
project_path: args.project_path,
|
||||
username: args.username,
|
||||
file_path: args.archive_path,
|
||||
measurement_enabled: Gitlab::Utils.to_boolean(args.measurement_enabled)
|
||||
).export
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class GitlabProjectExport
|
||||
include Gitlab::WithRequestStore
|
||||
|
||||
def initialize(opts)
|
||||
@project_path = opts.fetch(:project_path)
|
||||
@file_path = opts.fetch(:file_path)
|
||||
@current_user = User.find_by_username(opts.fetch(:username))
|
||||
namespace = Namespace.find_by_full_path(opts.fetch(:namespace_path))
|
||||
@project = namespace.projects.find_by_path(@project_path)
|
||||
@measurement_enabled = opts.fetch(:measurement_enabled)
|
||||
@measurable = Gitlab::Utils::Measuring.new if @measurement_enabled
|
||||
end
|
||||
|
||||
def export
|
||||
validate_project
|
||||
validate_file_path
|
||||
|
||||
with_export do
|
||||
::Projects::ImportExport::ExportService.new(project, current_user)
|
||||
.execute(Gitlab::ImportExport::AfterExportStrategies::MoveFileStrategy.new(archive_path: file_path))
|
||||
end
|
||||
|
||||
puts 'Done!'
|
||||
rescue StandardError => e
|
||||
puts "Exception: #{e.message}"
|
||||
puts e.backtrace
|
||||
exit 1
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :measurable, :project, :current_user, :file_path, :project_path
|
||||
|
||||
def validate_project
|
||||
unless project
|
||||
puts "Error: Project with path: #{project_path} was not found. Please provide correct project path"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
def validate_file_path
|
||||
directory = File.dirname(file_path)
|
||||
unless Dir.exist?(directory)
|
||||
puts "Error: Invalid file path: #{file_path}. Please provide correct file path"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
def with_export
|
||||
with_request_store do
|
||||
::Gitlab::GitalyClient.allow_n_plus_1_calls do
|
||||
measurement_enabled? ? measurable.with_measuring { yield } : yield
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def measurement_enabled?
|
||||
@measurement_enabled
|
||||
end
|
||||
end
|
|
@ -1,5 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'gitlab/with_request_store'
|
||||
|
||||
# Import large project archives
|
||||
#
|
||||
# This task:
|
||||
|
@ -27,19 +29,22 @@ namespace :gitlab do
|
|||
project_path: args.project_path,
|
||||
username: args.username,
|
||||
file_path: args.archive_path,
|
||||
measurement_enabled: args.measurement_enabled == 'true'
|
||||
measurement_enabled: Gitlab::Utils.to_boolean(args.measurement_enabled)
|
||||
).import
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class GitlabProjectImport
|
||||
include Gitlab::WithRequestStore
|
||||
|
||||
def initialize(opts)
|
||||
@project_path = opts.fetch(:project_path)
|
||||
@file_path = opts.fetch(:file_path)
|
||||
@namespace = Namespace.find_by_full_path(opts.fetch(:namespace_path))
|
||||
@current_user = User.find_by_username(opts.fetch(:username))
|
||||
@measurement_enabled = opts.fetch(:measurement_enabled)
|
||||
@measurement = Gitlab::Utils::Measuring.new if @measurement_enabled
|
||||
end
|
||||
|
||||
def import
|
||||
|
@ -49,11 +54,11 @@ class GitlabProjectImport
|
|||
|
||||
show_import_failures_count
|
||||
|
||||
if @project&.import_state&.last_error
|
||||
puts "ERROR: #{@project.import_state.last_error}"
|
||||
if project&.import_state&.last_error
|
||||
puts "ERROR: #{project.import_state.last_error}"
|
||||
exit 1
|
||||
elsif @project.errors.any?
|
||||
puts "ERROR: #{@project.errors.full_messages.join(', ')}"
|
||||
elsif project.errors.any?
|
||||
puts "ERROR: #{project.errors.full_messages.join(', ')}"
|
||||
exit 1
|
||||
else
|
||||
puts 'Done!'
|
||||
|
@ -66,60 +71,10 @@ class GitlabProjectImport
|
|||
|
||||
private
|
||||
|
||||
def with_request_store
|
||||
RequestStore.begin!
|
||||
yield
|
||||
ensure
|
||||
RequestStore.end!
|
||||
RequestStore.clear!
|
||||
end
|
||||
|
||||
def with_count_queries(&block)
|
||||
count = 0
|
||||
|
||||
counter_f = ->(name, started, finished, unique_id, payload) {
|
||||
unless payload[:name].in? %w[CACHE SCHEMA]
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
|
||||
ActiveSupport::Notifications.subscribed(counter_f, "sql.active_record", &block)
|
||||
|
||||
puts "Number of sql calls: #{count}"
|
||||
end
|
||||
|
||||
def with_gc_counter
|
||||
gc_counts_before = GC.stat.select { |k, v| k =~ /count/ }
|
||||
yield
|
||||
gc_counts_after = GC.stat.select { |k, v| k =~ /count/ }
|
||||
stats = gc_counts_before.merge(gc_counts_after) { |k, vb, va| va - vb }
|
||||
puts "Total GC count: #{stats[:count]}"
|
||||
puts "Minor GC count: #{stats[:minor_gc_count]}"
|
||||
puts "Major GC count: #{stats[:major_gc_count]}"
|
||||
end
|
||||
|
||||
def with_measure_time
|
||||
timing = Benchmark.realtime do
|
||||
yield
|
||||
end
|
||||
|
||||
time = Time.at(timing).utc.strftime("%H:%M:%S")
|
||||
puts "Time to finish: #{time}"
|
||||
end
|
||||
|
||||
def with_measuring
|
||||
puts "Measuring enabled..."
|
||||
with_gc_counter do
|
||||
with_count_queries do
|
||||
with_measure_time do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
attr_reader :measurement, :project, :namespace, :current_user, :file_path, :project_path
|
||||
|
||||
def measurement_enabled?
|
||||
@measurement_enabled != false
|
||||
@measurement_enabled
|
||||
end
|
||||
|
||||
# We want to ensure that all Sidekiq jobs are executed
|
||||
|
@ -135,7 +90,7 @@ class GitlabProjectImport
|
|||
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24475#note_283090635
|
||||
# For development setups, this code-path will be excluded from n+1 detection.
|
||||
::Gitlab::GitalyClient.allow_n_plus_1_calls do
|
||||
measurement_enabled? ? with_measuring { yield } : yield
|
||||
measurement_enabled? ? measurement.with_measuring { yield } : yield
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -158,11 +113,11 @@ class GitlabProjectImport
|
|||
# 2. Download of archive before unpacking
|
||||
disable_upload_object_storage do
|
||||
service = Projects::GitlabProjectsImportService.new(
|
||||
@current_user,
|
||||
current_user,
|
||||
{
|
||||
namespace_id: @namespace.id,
|
||||
path: @project_path,
|
||||
file: File.open(@file_path)
|
||||
namespace_id: namespace.id,
|
||||
path: project_path,
|
||||
file: File.open(file_path)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -193,18 +148,18 @@ class GitlabProjectImport
|
|||
end
|
||||
|
||||
def full_path
|
||||
"#{@namespace.full_path}/#{@project_path}"
|
||||
"#{namespace.full_path}/#{project_path}"
|
||||
end
|
||||
|
||||
def show_import_start_message
|
||||
puts "Importing GitLab export: #{@file_path} into GitLab" \
|
||||
puts "Importing GitLab export: #{file_path} into GitLab" \
|
||||
" #{full_path}" \
|
||||
" as #{@current_user.name}"
|
||||
" as #{current_user.name}"
|
||||
end
|
||||
|
||||
def show_import_failures_count
|
||||
return unless @project.import_failures.exists?
|
||||
return unless project.import_failures.exists?
|
||||
|
||||
puts "Total number of not imported relations: #{@project.import_failures.count}"
|
||||
puts "Total number of not imported relations: #{project.import_failures.count}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3480,6 +3480,9 @@ msgstr ""
|
|||
msgid "Checkout|Country"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Create a new group"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Credit card form failed to load. Please try again."
|
||||
msgstr ""
|
||||
|
||||
|
@ -3507,6 +3510,9 @@ msgstr ""
|
|||
msgid "Checkout|Failed to register credit card. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|GitLab group"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|GitLab plan"
|
||||
msgstr ""
|
||||
|
||||
|
@ -3531,6 +3537,9 @@ msgstr ""
|
|||
msgid "Checkout|Please select a state"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Select"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|State"
|
||||
msgstr ""
|
||||
|
||||
|
@ -3555,9 +3564,15 @@ msgstr ""
|
|||
msgid "Checkout|Users"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|You'll create your new group after checkout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Your organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Your subscription will be applied to this group"
|
||||
msgstr ""
|
||||
|
||||
msgid "Checkout|Zip code"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6865,12 +6880,18 @@ msgstr ""
|
|||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
msgid "Domain cannot be deleted while associated to one or more clusters."
|
||||
msgstr ""
|
||||
|
||||
msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
|
||||
msgstr ""
|
||||
|
||||
msgid "Domain was successfully created."
|
||||
msgstr ""
|
||||
|
||||
msgid "Domain was successfully deleted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Domain was successfully updated."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
"@babel/preset-env": "^7.6.2",
|
||||
"@gitlab/at.js": "^1.5.5",
|
||||
"@gitlab/svgs": "^1.99.0",
|
||||
"@gitlab/ui": "^9.11.1",
|
||||
"@gitlab/ui": "^9.11.2",
|
||||
"@gitlab/visual-review-tools": "1.5.1",
|
||||
"@sentry/browser": "^5.10.2",
|
||||
"@sourcegraph/code-host-integration": "0.0.30",
|
||||
|
|
|
@ -15,7 +15,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
get :index
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -33,7 +33,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
get :index
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -81,7 +81,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
post :create, params: { pages_domain: create_params }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,7 +98,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
post :create, params: { pages_domain: create_params }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -169,7 +169,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
put :update, params: { id: domain.id, pages_domain: update_params }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -186,7 +186,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
put :update, params: { id: domain.id, pages_domain: update_params }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -221,7 +221,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'returns 404' do
|
||||
put :update, params: { id: 0, pages_domain: update_params }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -247,7 +247,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
post :verify, params: { id: domain.id }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -272,7 +272,7 @@ describe Admin::Serverless::DomainsController do
|
|||
it 'responds with 404' do
|
||||
post :verify, params: { id: domain.id }
|
||||
|
||||
expect(response.status).to eq(404)
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -295,4 +295,76 @@ describe Admin::Serverless::DomainsController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
let!(:domain) { create(:pages_domain, :instance_serverless) }
|
||||
|
||||
context 'non-admin user' do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'responds with 404' do
|
||||
delete :destroy, params: { id: domain.id }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'admin user' do
|
||||
before do
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
context 'with serverless_domain feature disabled' do
|
||||
before do
|
||||
stub_feature_flags(serverless_domain: false)
|
||||
end
|
||||
|
||||
it 'responds with 404' do
|
||||
delete :destroy, params: { id: domain.id }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when domain exists' do
|
||||
context 'and is not associated to any clusters' do
|
||||
it 'deletes the domain' do
|
||||
expect { delete :destroy, params: { id: domain.id } }
|
||||
.to change { PagesDomain.count }.from(1).to(0)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:found)
|
||||
expect(flash[:notice]).to include('Domain was successfully deleted.')
|
||||
end
|
||||
end
|
||||
|
||||
context 'and is associated to any clusters' do
|
||||
before do
|
||||
create(:serverless_domain_cluster, pages_domain: domain)
|
||||
end
|
||||
|
||||
it 'does not delete the domain' do
|
||||
expect { delete :destroy, params: { id: domain.id } }
|
||||
.not_to change { PagesDomain.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:conflict)
|
||||
expect(flash[:notice]).to include('Domain cannot be deleted while associated to one or more clusters.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when domain does not exist' do
|
||||
before do
|
||||
domain.destroy!
|
||||
end
|
||||
|
||||
it 'responds with 404' do
|
||||
delete :destroy, params: { id: domain.id }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,9 +9,12 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
|
|||
class="btn btn-danger"
|
||||
type="button"
|
||||
>
|
||||
|
||||
Remove integration and resources
|
||||
|
||||
<span
|
||||
class="gl-dropdown-toggle-text"
|
||||
>
|
||||
Remove integration and resources
|
||||
</span>
|
||||
|
||||
<!---->
|
||||
</button>
|
||||
<button
|
||||
|
|
|
@ -613,6 +613,40 @@ describe Gitlab::Git::Blob, :seed_helper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#truncated?' do
|
||||
context 'when blob.size is nil' do
|
||||
let(:nil_size_blob) { Gitlab::Git::Blob.new(name: 'test', data: 'abcd') }
|
||||
|
||||
it 'returns false' do
|
||||
expect(nil_size_blob.truncated?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'when blob.data is missing' do
|
||||
let(:nil_data_blob) { Gitlab::Git::Blob.new(name: 'test', size: 4) }
|
||||
|
||||
it 'returns false' do
|
||||
expect(nil_data_blob.truncated?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the blob is truncated' do
|
||||
let(:truncated_blob) { Gitlab::Git::Blob.new(name: 'test', size: 40, data: 'abcd') }
|
||||
|
||||
it 'returns true' do
|
||||
expect(truncated_blob.truncated?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the blob is untruncated' do
|
||||
let(:untruncated_blob) { Gitlab::Git::Blob.new(name: 'test', size: 4, data: 'abcd') }
|
||||
|
||||
it 'returns false' do
|
||||
expect(untruncated_blob.truncated?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'metrics' do
|
||||
it 'defines :gitlab_blob_truncated_true counter' do
|
||||
expect(described_class).to respond_to(:gitlab_blob_truncated_true)
|
||||
|
|
|
@ -128,7 +128,7 @@ describe Gitlab::SidekiqConfig::CliMethods do
|
|||
resource_boundary: :cpu
|
||||
},
|
||||
{
|
||||
name: 'a_2',
|
||||
name: 'a:2',
|
||||
feature_category: :category_a,
|
||||
has_external_dependencies: false,
|
||||
latency_sensitive: true,
|
||||
|
@ -154,40 +154,40 @@ describe Gitlab::SidekiqConfig::CliMethods do
|
|||
context 'with valid input' do
|
||||
where(:query, :selected_queues) do
|
||||
# feature_category
|
||||
'feature_category=category_a' | %w(a a_2)
|
||||
'feature_category=category_a,category_c' | %w(a a_2 c)
|
||||
'feature_category=category_a|feature_category=category_c' | %w(a a_2 c)
|
||||
'feature_category=category_a' | %w(a a:2)
|
||||
'feature_category=category_a,category_c' | %w(a a:2 c)
|
||||
'feature_category=category_a|feature_category=category_c' | %w(a a:2 c)
|
||||
'feature_category!=category_a' | %w(b c)
|
||||
|
||||
# has_external_dependencies
|
||||
'has_external_dependencies=true' | %w(b)
|
||||
'has_external_dependencies=false' | %w(a a_2 c)
|
||||
'has_external_dependencies=true,false' | %w(a a_2 b c)
|
||||
'has_external_dependencies=true|has_external_dependencies=false' | %w(a a_2 b c)
|
||||
'has_external_dependencies!=true' | %w(a a_2 c)
|
||||
'has_external_dependencies=false' | %w(a a:2 c)
|
||||
'has_external_dependencies=true,false' | %w(a a:2 b c)
|
||||
'has_external_dependencies=true|has_external_dependencies=false' | %w(a a:2 b c)
|
||||
'has_external_dependencies!=true' | %w(a a:2 c)
|
||||
|
||||
# latency_sensitive
|
||||
'latency_sensitive=true' | %w(a_2 b)
|
||||
'latency_sensitive=true' | %w(a:2 b)
|
||||
'latency_sensitive=false' | %w(a c)
|
||||
'latency_sensitive=true,false' | %w(a a_2 b c)
|
||||
'latency_sensitive=true|latency_sensitive=false' | %w(a a_2 b c)
|
||||
'latency_sensitive=true,false' | %w(a a:2 b c)
|
||||
'latency_sensitive=true|latency_sensitive=false' | %w(a a:2 b c)
|
||||
'latency_sensitive!=true' | %w(a c)
|
||||
|
||||
# name
|
||||
'name=a' | %w(a)
|
||||
'name=a,b' | %w(a b)
|
||||
'name=a,a_2|name=b' | %w(a a_2 b)
|
||||
'name!=a,a_2' | %w(b c)
|
||||
'name=a,a:2|name=b' | %w(a a:2 b)
|
||||
'name!=a,a:2' | %w(b c)
|
||||
|
||||
# resource_boundary
|
||||
'resource_boundary=memory' | %w(b c)
|
||||
'resource_boundary=memory,cpu' | %w(a b c)
|
||||
'resource_boundary=memory|resource_boundary=cpu' | %w(a b c)
|
||||
'resource_boundary!=memory,cpu' | %w(a_2)
|
||||
'resource_boundary!=memory,cpu' | %w(a:2)
|
||||
|
||||
# combinations
|
||||
'feature_category=category_a&latency_sensitive=true' | %w(a_2)
|
||||
'feature_category=category_a&latency_sensitive=true|feature_category=category_c' | %w(a_2 c)
|
||||
'feature_category=category_a&latency_sensitive=true' | %w(a:2)
|
||||
'feature_category=category_a&latency_sensitive=true|feature_category=category_c' | %w(a:2 c)
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
|
@ -9,6 +9,7 @@ describe PagesDomain do
|
|||
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to have_many(:serverless_domain_clusters) }
|
||||
end
|
||||
|
||||
describe 'validate domain' do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'import measurement' do
|
||||
RSpec.shared_examples 'measurable' do
|
||||
context 'when measurement is enabled' do
|
||||
let(:measurement_enabled) { true }
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rake_helper'
|
||||
|
||||
describe 'gitlab:import_export:export rake task' do
|
||||
let(:username) { 'root' }
|
||||
let(:namespace_path) { username }
|
||||
let!(:user) { create(:user, username: username) }
|
||||
let(:measurement_enabled) { false }
|
||||
let(:task_params) { [username, namespace_path, project_name, archive_path, measurement_enabled] }
|
||||
|
||||
before do
|
||||
Rake.application.rake_require('tasks/gitlab/import_export/export')
|
||||
end
|
||||
|
||||
subject { run_rake_task('gitlab:import_export:export', task_params) }
|
||||
|
||||
context 'when project is found' do
|
||||
let(:project) { create(:project, creator: user, namespace: user.namespace) }
|
||||
let(:project_name) { project.name }
|
||||
let(:archive_path) { 'spec/fixtures/gitlab/import_export/test_project_export.tar.gz' }
|
||||
|
||||
around do |example|
|
||||
example.run
|
||||
ensure
|
||||
File.delete(archive_path)
|
||||
end
|
||||
|
||||
it 'performs project export successfully' do
|
||||
expect { subject }.to output(/Done!/).to_stdout
|
||||
|
||||
expect(File).to exist(archive_path)
|
||||
end
|
||||
|
||||
it_behaves_like 'measurable'
|
||||
end
|
||||
end
|
|
@ -70,7 +70,7 @@ describe 'gitlab:import_export:import rake task' do
|
|||
subject
|
||||
end
|
||||
|
||||
it_behaves_like 'import measurement'
|
||||
it_behaves_like 'measurable'
|
||||
end
|
||||
|
||||
context 'when project import is invalid' do
|
||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -745,10 +745,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.99.0.tgz#bcf971c3a14920218e86da71ca115244b23a4a3f"
|
||||
integrity sha512-bxYFxnmuoWPBU9isL3/CYFlr+k2YWU47Pq0vfmSmL7uLnb/vYymfZZF5p3erlZ62WGwuT3kp4GnuoZBMfmannA==
|
||||
|
||||
"@gitlab/ui@^9.11.1":
|
||||
version "9.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.11.1.tgz#f234687d2d1b555ebeaf05156e16b4fd97aef453"
|
||||
integrity sha512-3INIA2n9rxz+VCc0hO4EnmET00XCAMS25hHnIJ6ffKeJz40diCvEZ6Asusv4BiIPosmTyz8VufYGQRq+8v8rNQ==
|
||||
"@gitlab/ui@^9.11.2":
|
||||
version "9.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.11.2.tgz#ffb58bb10c6a8cd503a622946ed78512e9c18c6d"
|
||||
integrity sha512-9acsjQ9+hSaAIGpiARNF4XfQUhulWiausns9JUTrN9XEQpa1o/EsDYqwP0HfSOMZ8JhnjSI2NGYVf+LIH5oudg==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
"@gitlab/vue-toasted" "^1.3.0"
|
||||
|
@ -11626,16 +11626,11 @@ uuid@3.3.2, uuid@^3.0.1, uuid@^3.3.2:
|
|||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
|
||||
|
||||
v8-compile-cache@2.0.3:
|
||||
v8-compile-cache@2.0.3, v8-compile-cache@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
|
||||
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
|
||||
|
||||
v8-compile-cache@^2.0.3:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
|
||||
integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==
|
||||
|
||||
validate-npm-package-license@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
|
||||
|
|
Loading…
Reference in New Issue