Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7510df057e
commit
308d6fce18
|
@ -70,12 +70,12 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
mdTable() {
|
||||
const header = 'header';
|
||||
return [
|
||||
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
|
||||
'| header | header |', // eslint-disable-line @gitlab/require-i18n-strings
|
||||
`| ${header} | ${header} |`,
|
||||
'| ------ | ------ |',
|
||||
'| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings
|
||||
'| cell | cell |', // eslint-disable-line @gitlab/require-i18n-strings
|
||||
'| | |',
|
||||
'| | |',
|
||||
].join('\n');
|
||||
},
|
||||
mdSuggestion() {
|
||||
|
|
|
@ -41,7 +41,7 @@ class MergeRequest < ApplicationRecord
|
|||
'Ci::CompareCodequalityReportsService' => ->(project) { true }
|
||||
}.freeze
|
||||
|
||||
MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 100
|
||||
MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS = 200
|
||||
|
||||
belongs_to :target_project, class_name: "Project"
|
||||
belongs_to :source_project, class_name: "Project"
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
f7c4b6a31434a0f6487fef89ba0c60fd38169e901437667bb6ccf60ba1a3bd4d
|
|
@ -0,0 +1 @@
|
|||
352e1b200a7e5074c58fdcfd0c9ae9b3535054a0b3d9852caabde635d9a1ad94
|
|
@ -0,0 +1 @@
|
|||
9cdc6169dc4925f43aabb2f4bcf597333a4112135001a5d1a6961853a78c90da
|
|
@ -11485,6 +11485,9 @@ CREATE TABLE application_settings (
|
|||
dashboard_enforcement_limit integer DEFAULT 0 NOT NULL,
|
||||
dashboard_limit_new_namespace_creation_enforcement_date date,
|
||||
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_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)),
|
||||
|
@ -17868,6 +17871,12 @@ CREATE TABLE namespace_package_settings (
|
|||
maven_duplicate_exception_regex text DEFAULT ''::text NOT NULL,
|
||||
generic_duplicates_allowed boolean DEFAULT true 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_d63274b2b6 CHECK ((char_length(maven_duplicate_exception_regex) <= 255))
|
||||
);
|
||||
|
|
|
@ -25,13 +25,17 @@ module QA
|
|||
module Tools
|
||||
class TestResourcesHandler
|
||||
include Support::API
|
||||
include Ci::Helpers
|
||||
|
||||
IGNORED_RESOURCES = [
|
||||
'QA::Resource::CiVariable',
|
||||
'QA::Resource::Repository::Commit',
|
||||
'QA::EE::Resource::GroupIteration',
|
||||
'QA::EE::Resource::Settings::Elasticsearch',
|
||||
'QA::EE::Resource::VulnerabilityItem'
|
||||
IGNORED_RESOURCES = %w[
|
||||
QA::Resource::CiVariable
|
||||
QA::Resource::Repository::Commit
|
||||
QA::Resource::Design
|
||||
QA::EE::Resource::GroupIteration
|
||||
QA::EE::Resource::Settings::Elasticsearch
|
||||
QA::EE::Resource::VulnerabilityItem
|
||||
QA::EE::Resource::ScanResultPolicyProject
|
||||
QA::EE::Resource::ScanResultPolicyCommit
|
||||
].freeze
|
||||
|
||||
PROJECT = 'gitlab-qa-resources'
|
||||
|
@ -44,10 +48,19 @@ module QA
|
|||
def run_delete
|
||||
failures = files.flat_map do |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)
|
||||
if filtered_resources.nil?
|
||||
logger.info("No resources left to delete after filtering!")
|
||||
next
|
||||
end
|
||||
|
||||
delete_resources(filtered_resources)
|
||||
delete_groups_permanently(filtered_resources['QA::Resource::Group'])
|
||||
end
|
||||
|
||||
return puts "\nDone" if failures.empty?
|
||||
|
@ -62,17 +75,15 @@ module QA
|
|||
# E.g: staging/failed-test-resources-<randomhex>.json
|
||||
def upload(ci_project_name)
|
||||
if files.empty?
|
||||
puts "\nNothing to upload!"
|
||||
exit 0
|
||||
logger.info("\nNothing to upload!")
|
||||
return
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
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))
|
||||
end
|
||||
|
||||
puts "\nDone"
|
||||
end
|
||||
|
||||
# Download files from GCS bucket by environment name
|
||||
|
@ -85,40 +96,38 @@ module QA
|
|||
end
|
||||
|
||||
if files_list.blank?
|
||||
puts "\nNothing to download!"
|
||||
exit 0
|
||||
logger.info("\nNothing to download!")
|
||||
return
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p('tmp/')
|
||||
|
||||
files_list.each do |file_name|
|
||||
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.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)
|
||||
end
|
||||
|
||||
puts "\nDone"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def files
|
||||
Runtime::Logger.info('Gathering JSON files...')
|
||||
logger.info('Gathering JSON files...')
|
||||
files = Dir.glob(@file_pattern)
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
files.reject! { |file| File.zero?(file) }
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -126,14 +135,15 @@ module QA
|
|||
end
|
||||
|
||||
def read_file(file)
|
||||
logger.info("Reading and processing #{file}...")
|
||||
JSON.parse(File.read(file))
|
||||
rescue JSON::ParserError
|
||||
Runtime::Logger.error("Failed to read #{file} - Invalid format")
|
||||
logger.error("Failed to read #{file} - Invalid format")
|
||||
nil
|
||||
end
|
||||
|
||||
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|
|
||||
v.reject do |attributes|
|
||||
|
@ -147,28 +157,55 @@ module QA
|
|||
end
|
||||
|
||||
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|
|
||||
value.each do |resource|
|
||||
next if resource_not_found?(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)
|
||||
|
||||
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
|
||||
Runtime::Logger.info("Deleting #{resource_info}... FAILED - #{delete_response}")
|
||||
failures << resource_info
|
||||
logger.info("Deleting #{resource_info}... \e[31mFAILED - #{delete_response}\e[0m")
|
||||
# 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
|
||||
|
||||
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)
|
||||
# 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
|
||||
|
|
|
@ -5,8 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe 'Projects > Show > Collaboration links', :js do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:project) { create(:project, :repository, :public) }
|
||||
let(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :repository, :public) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
@ -17,7 +17,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
|
|||
end
|
||||
|
||||
context 'with developer user' do
|
||||
before do
|
||||
before_all do
|
||||
project.add_developer(user)
|
||||
end
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ describe('Markdown field header component', () => {
|
|||
const tableButton = findToolbarButtonByProp('icon', 'table');
|
||||
|
||||
expect(tableButton.props('tag')).toEqual(
|
||||
'| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |',
|
||||
'| header | header |\n| ------ | ------ |\n| | |\n| | |',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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
|
||||
|
||||
|
@ -30,7 +30,7 @@ gem install microsoft_graph_mailer
|
|||
|
||||
To use the Microsoft Graph API to send mails, you will
|
||||
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. Search for and select `Azure Active Directory`.
|
||||
|
|
Loading…
Reference in New Issue