Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-09-30 21:08:17 +00:00
parent 7510df057e
commit 308d6fce18
13 changed files with 177 additions and 44 deletions

View File

@ -70,12 +70,12 @@ export default {
}, },
computed: { computed: {
mdTable() { mdTable() {
const header = 'header';
return [ return [
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26 `| ${header} | ${header} |`,
'| header | header |', // eslint-disable-line @gitlab/require-i18n-strings
'| ------ | ------ |', '| ------ | ------ |',
'| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings '| | |',
'| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings '| | |',
].join('\n'); ].join('\n');
}, },
mdSuggestion() { mdSuggestion() {

View File

@ -41,7 +41,7 @@ class MergeRequest < ApplicationRecord
'Ci::CompareCodequalityReportsService' => ->(project) { true } 'Ci::CompareCodequalityReportsService' => ->(project) { true }
}.freeze }.freeze
MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 100 MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 200
belongs_to :target_project, class_name: "Project" belongs_to :target_project, class_name: "Project"
belongs_to :source_project, class_name: "Project" belongs_to :source_project, class_name: "Project"

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class AddMavenPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
def change
# adds columns to match the format used in
# Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
add_column(:namespace_package_settings,
:maven_package_requests_forwarding,
:boolean,
null: true,
default: nil
)
add_column(:namespace_package_settings,
:lock_maven_package_requests_forwarding,
:boolean,
default: false,
null: false
)
add_column(:application_settings,
:lock_maven_package_requests_forwarding,
:boolean,
default: false,
null: false
)
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class AddPypiPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
def change
# adds columns to match the format used in
# Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
add_column(:namespace_package_settings,
:pypi_package_requests_forwarding,
:boolean,
null: true,
default: nil
)
add_column(:namespace_package_settings,
:lock_pypi_package_requests_forwarding,
:boolean,
default: false,
null: false
)
add_column(:application_settings,
:lock_pypi_package_requests_forwarding,
:boolean,
default: false,
null: false
)
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class AddNpmPackageRequestsForwardingToNamespacePackageSettings < Gitlab::Database::Migration[2.0]
def change
# adds columns to match the format used in
# Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings#add_cascading_namespace_setting
add_column(:namespace_package_settings,
:npm_package_requests_forwarding,
:boolean,
null: true,
default: nil
)
add_column(:namespace_package_settings,
:lock_npm_package_requests_forwarding,
:boolean,
default: false,
null: false
)
add_column(:application_settings,
:lock_npm_package_requests_forwarding,
:boolean,
default: false,
null: false
)
end
end

View File

@ -0,0 +1 @@
f7c4b6a31434a0f6487fef89ba0c60fd38169e901437667bb6ccf60ba1a3bd4d

View File

@ -0,0 +1 @@
352e1b200a7e5074c58fdcfd0c9ae9b3535054a0b3d9852caabde635d9a1ad94

View File

@ -0,0 +1 @@
9cdc6169dc4925f43aabb2f4bcf597333a4112135001a5d1a6961853a78c90da

View File

@ -11485,6 +11485,9 @@ CREATE TABLE application_settings (
dashboard_enforcement_limit integer DEFAULT 0 NOT NULL, dashboard_enforcement_limit integer DEFAULT 0 NOT NULL,
dashboard_limit_new_namespace_creation_enforcement_date date, dashboard_limit_new_namespace_creation_enforcement_date date,
can_create_group boolean DEFAULT true NOT NULL, can_create_group boolean DEFAULT true NOT NULL,
lock_maven_package_requests_forwarding boolean DEFAULT false NOT NULL,
lock_pypi_package_requests_forwarding boolean DEFAULT false NOT NULL,
lock_npm_package_requests_forwarding boolean DEFAULT false NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
@ -17868,6 +17871,12 @@ CREATE TABLE namespace_package_settings (
maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL, maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
generic_duplicates_allowed boolean DEFAULT true NOT NULL, generic_duplicates_allowed boolean DEFAULT true NOT NULL,
generic_duplicate_exception_regex text DEFAULT ''::text NOT NULL, generic_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
maven_package_requests_forwarding boolean,
lock_maven_package_requests_forwarding boolean DEFAULT false NOT NULL,
pypi_package_requests_forwarding boolean,
lock_pypi_package_requests_forwarding boolean DEFAULT false NOT NULL,
npm_package_requests_forwarding boolean,
lock_npm_package_requests_forwarding boolean DEFAULT false NOT NULL,
CONSTRAINT check_31340211b1 CHECK ((char_length(generic_duplicate_exception_regex) <= 255)), CONSTRAINT check_31340211b1 CHECK ((char_length(generic_duplicate_exception_regex) <= 255)),
CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255)) CONSTRAINT check_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255))
); );

View File

@ -25,13 +25,17 @@ module QA
module Tools module Tools
class TestResourcesHandler class TestResourcesHandler
include Support::API include Support::API
include Ci::Helpers
IGNORED_RESOURCES = [ IGNORED_RESOURCES = %w[
'QA::Resource::CiVariable', QA::Resource::CiVariable
'QA::Resource::Repository::Commit', QA::Resource::Repository::Commit
'QA::EE::Resource::GroupIteration', QA::Resource::Design
'QA::EE::Resource::Settings::Elasticsearch', QA::EE::Resource::GroupIteration
'QA::EE::Resource::VulnerabilityItem' QA::EE::Resource::Settings::Elasticsearch
QA::EE::Resource::VulnerabilityItem
QA::EE::Resource::ScanResultPolicyProject
QA::EE::Resource::ScanResultPolicyCommit
].freeze ].freeze
PROJECT = 'gitlab-qa-resources' PROJECT = 'gitlab-qa-resources'
@ -44,10 +48,19 @@ module QA
def run_delete def run_delete
failures = files.flat_map do |file| failures = files.flat_map do |file|
resources = read_file(file) resources = read_file(file)
next if resources.nil? if resources.nil?
logger.info("#{file} is empty, next...")
next
end
filtered_resources = filter_resources(resources) filtered_resources = filter_resources(resources)
if filtered_resources.nil?
logger.info("No resources left to delete after filtering!")
next
end
delete_resources(filtered_resources) delete_resources(filtered_resources)
delete_groups_permanently(filtered_resources['QA::Resource::Group'])
end end
return puts "\nDone" if failures.empty? return puts "\nDone" if failures.empty?
@ -62,17 +75,15 @@ module QA
# E.g: staging/failed-test-resources-<randomhex>.json # E.g: staging/failed-test-resources-<randomhex>.json
def upload(ci_project_name) def upload(ci_project_name)
if files.empty? if files.empty?
puts "\nNothing to upload!" logger.info("\nNothing to upload!")
exit 0 return
end end
files.each do |file| files.each do |file|
file_name = "#{ci_project_name}/#{file.split('/').last}" file_name = "#{ci_project_name}/#{file.split('/').last}"
Runtime::Logger.info("Uploading #{file_name}...") logger.info("Uploading #{file_name}...")
gcs_storage.put_object(BUCKET, file_name, File.read(file)) gcs_storage.put_object(BUCKET, file_name, File.read(file))
end end
puts "\nDone"
end end
# Download files from GCS bucket by environment name # Download files from GCS bucket by environment name
@ -85,40 +96,38 @@ module QA
end end
if files_list.blank? if files_list.blank?
puts "\nNothing to download!" logger.info("\nNothing to download!")
exit 0 return
end end
FileUtils.mkdir_p('tmp/') FileUtils.mkdir_p('tmp/')
files_list.each do |file_name| files_list.each do |file_name|
local_path = "tmp/#{file_name.split('/').last}" local_path = "tmp/#{file_name.split('/').last}"
Runtime::Logger.info("Downloading #{file_name} to #{local_path}") logger.info("Downloading #{file_name} to #{local_path}")
file = gcs_storage.get_object(BUCKET, file_name) file = gcs_storage.get_object(BUCKET, file_name)
File.write(local_path, file[:body]) File.write(local_path, file[:body])
Runtime::Logger.info("Deleting #{file_name} from bucket") logger.info("Deleting #{file_name} from bucket")
gcs_storage.delete_object(BUCKET, file_name) gcs_storage.delete_object(BUCKET, file_name)
end end
puts "\nDone"
end end
private private
def files def files
Runtime::Logger.info('Gathering JSON files...') logger.info('Gathering JSON files...')
files = Dir.glob(@file_pattern) files = Dir.glob(@file_pattern)
if files.empty? if files.empty?
puts "There is no file with this pattern #{@file_pattern}" logger.info("There is no file with this pattern #{@file_pattern}")
exit 0 exit 0
end end
files.reject! { |file| File.zero?(file) } files.reject! { |file| File.zero?(file) }
if files.empty? if files.empty?
puts "\nAll files were empty and rejected, nothing more to do!" logger.info("\nAll files were empty and rejected, nothing more to do!")
exit 0 exit 0
end end
@ -126,14 +135,15 @@ module QA
end end
def read_file(file) def read_file(file)
logger.info("Reading and processing #{file}...")
JSON.parse(File.read(file)) JSON.parse(File.read(file))
rescue JSON::ParserError rescue JSON::ParserError
Runtime::Logger.error("Failed to read #{file} - Invalid format") logger.error("Failed to read #{file} - Invalid format")
nil nil
end end
def filter_resources(resources) def filter_resources(resources)
Runtime::Logger.info('Filtering resources - Only keep deletable resources...') logger.info('Filtering resources - Only keep deletable resources...')
transformed_values = resources.transform_values! do |v| transformed_values = resources.transform_values! do |v|
v.reject do |attributes| v.reject do |attributes|
@ -147,28 +157,55 @@ module QA
end end
def delete_resources(resources) def delete_resources(resources)
if resources.nil?
puts "\nNo resources left to delete after filtering!"
exit 0
end
resources.each_with_object([]) do |(key, value), failures| resources.each_with_object([]) do |(key, value), failures|
value.each do |resource| value.each do |resource|
next if resource_not_found?(resource['api_path'])
resource_info = resource['info'] ? "#{key} - #{resource['info']}" : "#{key} at #{resource['api_path']}" resource_info = resource['info'] ? "#{key} - #{resource['info']}" : "#{key} at #{resource['api_path']}"
logger.info("Processing #{resource_info}...")
if resource_not_found?(resource['api_path'])
logger.info("#{resource['api_path']} returns 404, next...")
next
end
delete_response = delete(Runtime::API::Request.new(api_client, resource['api_path']).url) delete_response = delete(Runtime::API::Request.new(api_client, resource['api_path']).url)
if delete_response.code == 202 || delete_response.code == 204 if delete_response.code == 202 || delete_response.code == 204
Runtime::Logger.info("Deleting #{resource_info}... SUCCESS") if key == 'QA::Resource::Group' && !resource_not_found?(resource['api_path'])
logger.info("Successfully marked #{resource_info} for deletion...")
else
logger.info("Deleting #{resource_info}... \e[32mSUCCESS\e[0m")
end
else else
Runtime::Logger.info("Deleting #{resource_info}... FAILED - #{delete_response}") logger.info("Deleting #{resource_info}... \e[31mFAILED - #{delete_response}\e[0m")
failures << resource_info # We might try to delete some groups already marked for deletion, it's fine to ignore these failures
failures << resource_info unless key == 'QA::Resource::Group'
end end
end end
end end
end end
def delete_groups_permanently(groups)
groups.each_with_object([]) do |group, failures|
logger.info("Processing QA::Resource::Group #{group['info']}...")
if resource_not_found?(group['api_path'])
logger.info("#{group['api_path']} returns 404, next...")
next
end
permanent_delete_path = "#{group['api_path']}?permanently_remove=true"\
"&full_path=#{group['info'].split("'").last}"
response = delete(Runtime::API::Request.new(api_client, permanent_delete_path).url)
if response.code == 202
logger.info("Permanently deleting group #{group['info']}... \e[32mSUCCESS\e[0m")
else
logger.info("Permanently deleting group #{group['info']}... \e[31mFAILED - #{response}\e[0m")
failures << "QA::Resource::Group #{group['info']}"
end
end
end
def resource_not_found?(api_path) def resource_not_found?(api_path)
# if api path contains param "?hard_delete=<boolean>", remove it # if api path contains param "?hard_delete=<boolean>", remove it
get(Runtime::API::Request.new(api_client, api_path.split('?').first).url).code.eql? 404 get(Runtime::API::Request.new(api_client, api_path.split('?').first).url).code.eql? 404

View File

@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Projects > Show > Collaboration links', :js do RSpec.describe 'Projects > Show > Collaboration links', :js do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let(:project) { create(:project, :repository, :public) } let_it_be(:project) { create(:project, :repository, :public) }
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
before do before do
sign_in(user) sign_in(user)
@ -17,7 +17,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
end end
context 'with developer user' do context 'with developer user' do
before do before_all do
project.add_developer(user) project.add_developer(user)
end end

View File

@ -142,7 +142,7 @@ describe('Markdown field header component', () => {
const tableButton = findToolbarButtonByProp('icon', 'table'); const tableButton = findToolbarButtonByProp('icon', 'table');
expect(tableButton.props('tag')).toEqual( expect(tableButton.props('tag')).toEqual(
'| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |', '| header | header |\n| ------ | ------ |\n| | |\n| | |',
); );
}); });

View File

@ -1,6 +1,6 @@
# microsoft_graph_mailer # microsoft_graph_mailer
This gem allows delivery of emails using [Microsoft Graph API](https://docs.microsoft.com/en-us/graph/api/user-sendmail) with [OAuth 2.0 client credentials flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow). This gem allows delivery of emails using [Microsoft Graph API](https://learn.microsoft.com/en-us/graph/api/user-sendmail) with [OAuth 2.0 client credentials flow](https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).
## The reason for this gem ## The reason for this gem
@ -30,7 +30,7 @@ gem install microsoft_graph_mailer
To use the Microsoft Graph API to send mails, you will To use the Microsoft Graph API to send mails, you will
need to create an application in the Azure Active Directory. See the need to create an application in the Azure Active Directory. See the
[Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details: [Microsoft instructions](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details:
1. Sign in to the [Azure portal](https://portal.azure.com). 1. Sign in to the [Azure portal](https://portal.azure.com).
1. Search for and select `Azure Active Directory`. 1. Search for and select `Azure Active Directory`.