Add latest changes from gitlab-org/gitlab@master
|
|
@ -367,6 +367,7 @@ jest-with-fixtures vue3 mr:
|
|||
when: always
|
||||
paths:
|
||||
- junit_jest.xml
|
||||
parallel: 1
|
||||
script:
|
||||
- run_timed_command "yarn jest:ci:vue3-mr:with-fixtures"
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
14.38.0
|
||||
14.39.0
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ ul.related-merge-requests > li gl-emoji {
|
|||
right: var(--application-bar-right);
|
||||
width: auto;
|
||||
top: $calc-application-header-height;
|
||||
max-width: calc(100vw - #{$super-sidebar-width});
|
||||
}
|
||||
|
||||
.limit-container-width {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module LinkableItem
|
|||
include IssuableLink
|
||||
|
||||
included do
|
||||
validate :check_existing_parent_link
|
||||
validate :check_existing_parent_link, on: :create
|
||||
|
||||
scope :for_source, ->(item) { where(source_id: item.id) }
|
||||
scope :for_target, ->(item) { where(target_id: item.id) }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module WorkItems
|
|||
validate :validate_cyclic_reference
|
||||
validate :validate_max_children
|
||||
validate :validate_confidentiality
|
||||
validate :check_existing_related_link
|
||||
validate :check_existing_related_link, on: :create
|
||||
|
||||
scope :for_parents, ->(parent_ids) { where(work_item_parent_id: parent_ids) }
|
||||
scope :for_children, ->(children_ids) { where(work_item: children_ids) }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# As discussed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148637#note_1850247875,
|
||||
# Rails 7.1 introduces enqueue_all which is not covered in this patch.
|
||||
# We deliver emails using the `deliver_later` method and it uses ActiveJob
|
||||
# under the hood, which later processes the email via the defined ActiveJob adapter's `enqueue` method.
|
||||
# For GitLab, the ActiveJob adapter is Sidekiq (in development and production environments).
|
||||
#
|
||||
# We need to set the following up to override the ActiveJob adapater
|
||||
# so as to ensure that mailer jobs are enqueued in a shard-aware manner.
|
||||
|
||||
|
|
@ -15,8 +14,18 @@ end
|
|||
module ActiveJob
|
||||
module QueueAdapters
|
||||
module ActiveJobShardSupport
|
||||
if ::Gitlab.next_rails?
|
||||
def enqueue_all(jobs)
|
||||
Gitlab::SidekiqSharding::Router.route(ActionMailer::MailDeliveryJob) do
|
||||
super(jobs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%i[enqueue enqueue_at].each do |name|
|
||||
define_method(name) do |*args|
|
||||
return super(*args) if ::Gitlab.next_rails?
|
||||
|
||||
Gitlab::SidekiqSharding::Router.route(ActionMailer::MailDeliveryJob) do
|
||||
super(*args)
|
||||
end
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -11,7 +11,25 @@ module Gitlab
|
|||
# so we only need to patch 1 method.
|
||||
def perform_async(*args)
|
||||
# rubocop:disable Gitlab/ModuleWithInstanceVariables -- @klass is present in the class we are patching
|
||||
Gitlab::SidekiqSharding::Router.route(@klass) do
|
||||
|
||||
route_with_klass = @klass
|
||||
|
||||
# If an ActiveJob JobWrapper is pushed, check the arg hash's job_class for routing decisions.
|
||||
#
|
||||
# See https://github.com/rails/rails/blob/v7.1.0/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb#L21
|
||||
# `job.serialize` would return a hash containing `job_class` set in
|
||||
# https://github.com/rails/rails/blob/v7.1.0/activejob/lib/active_job/core.rb#L110
|
||||
#
|
||||
# In the GitLab Rails application, this only applies to ActionMailer::MailDeliveryJob
|
||||
# but routing using the `job_class` keeps the option of using ActiveJob available for us.
|
||||
#
|
||||
if @klass == ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper &&
|
||||
args.first.is_a?(Hash) &&
|
||||
args.first['job_class']
|
||||
route_with_klass = args.first['job_class'].to_s.safe_constantize
|
||||
end
|
||||
|
||||
Gitlab::SidekiqSharding::Router.route(route_with_klass) do
|
||||
# rubocop:enable Gitlab/ModuleWithInstanceVariables
|
||||
super
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ namespace :gitlab do
|
|||
File.open("config.yml", "w+") { |f| f.puts config.to_yaml }
|
||||
|
||||
[
|
||||
%w[bin/install],
|
||||
%w[make build]
|
||||
%w[make make_necessary_dirs build]
|
||||
].each do |cmd|
|
||||
unless Kernel.system(*cmd)
|
||||
raise "command failed: #{cmd.join(' ')}"
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@
|
|||
"yaml": "^2.0.0-10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gitlab/eslint-plugin": "19.6.1",
|
||||
"@gitlab/eslint-plugin": "20.0.0",
|
||||
"@gitlab/stylelint-config": "6.2.1",
|
||||
"@graphql-eslint/eslint-plugin": "3.20.1",
|
||||
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,66 @@ RSpec.describe WorkItems::ParentLink, feature_category: :portfolio_management do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when parent is already linked' do
|
||||
shared_examples 'invalid link' do |link_factory|
|
||||
let_it_be(:parent_link) { build(:parent_link, work_item_parent: issue, work_item: task1) }
|
||||
let(:error_msg) { 'cannot assign a linked work item as a parent' }
|
||||
|
||||
context 'when creating new link' do
|
||||
context 'when parent is the link target' do
|
||||
before do
|
||||
create(link_factory, source_id: task1.id, target_id: issue.id)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).not_to be_valid
|
||||
expect(parent_link.errors[:work_item]).to include(error_msg)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parent is the link source' do
|
||||
before do
|
||||
create(link_factory, source_id: issue.id, target_id: task1.id)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).not_to be_valid
|
||||
expect(parent_link.errors[:work_item]).to include(error_msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when updating existing link' do
|
||||
context 'when parent is the link target' do
|
||||
before do
|
||||
create(link_factory, source_id: task1.id, target_id: issue.id)
|
||||
parent_link.save!(validate: false)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).to be_valid
|
||||
expect(parent_link.errors[:work_item]).not_to include(error_msg)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parent is the link source' do
|
||||
before do
|
||||
create(link_factory, source_id: issue.id, target_id: task1.id)
|
||||
parent_link.save!(validate: false)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).to be_valid
|
||||
expect(parent_link.errors[:work_item]).not_to include(error_msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'invalid link', :work_item_link
|
||||
it_behaves_like 'invalid link', :issue_link
|
||||
end
|
||||
|
||||
context 'when setting confidentiality' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
|
|
@ -191,38 +251,6 @@ RSpec.describe WorkItems::ParentLink, feature_category: :portfolio_management do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parent is already linked' do
|
||||
shared_examples 'invalid link' do |link_factory|
|
||||
let_it_be(:parent_link) { build(:parent_link, work_item_parent: issue, work_item: task1) }
|
||||
let(:error_msg) { 'cannot assign a linked work item as a parent' }
|
||||
|
||||
context 'when parent is the link target' do
|
||||
before do
|
||||
create(link_factory, source_id: task1.id, target_id: issue.id)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).not_to be_valid
|
||||
expect(parent_link.errors[:work_item]).to include(error_msg)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parent is the link source' do
|
||||
before do
|
||||
create(link_factory, source_id: issue.id, target_id: task1.id)
|
||||
end
|
||||
|
||||
it do
|
||||
expect(parent_link).not_to be_valid
|
||||
expect(parent_link.errors[:work_item]).to include(error_msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'invalid link', :work_item_link
|
||||
it_behaves_like 'invalid link', :issue_link
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,34 +8,65 @@ RSpec.shared_examples 'includes LinkableItem concern' do
|
|||
subject(:link) { build(link_factory, source_id: source.id, target_id: target.id) }
|
||||
|
||||
describe '#check_existing_parent_link' do
|
||||
shared_examples 'invalid due to existing link' do
|
||||
it do
|
||||
is_expected.to be_invalid
|
||||
expect(link.errors.messages[:source]).to include("is a parent or child of this #{item_type}")
|
||||
context 'for new issuable link' do
|
||||
shared_examples 'invalid due to existing link' do
|
||||
it do
|
||||
is_expected.to be_invalid
|
||||
expect(link.errors.messages[:source]).to include("is a parent or child of this #{item_type}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without existing link parent' do
|
||||
let(:source) { issue }
|
||||
let(:target) { task }
|
||||
|
||||
it 'is valid' do
|
||||
is_expected.to be_valid
|
||||
expect(link.errors).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'with existing link parent' do
|
||||
let_it_be(:relationship) { create(:parent_link, work_item_parent: issue, work_item: task) }
|
||||
|
||||
it_behaves_like 'invalid due to existing link' do
|
||||
context 'without existing link parent' do
|
||||
let(:source) { issue }
|
||||
let(:target) { task }
|
||||
|
||||
it 'is valid' do
|
||||
is_expected.to be_valid
|
||||
expect(link.errors).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'invalid due to existing link' do
|
||||
context 'with existing link parent' do
|
||||
let_it_be(:relationship) { create(:parent_link, work_item_parent: issue, work_item: task) }
|
||||
|
||||
it_behaves_like 'invalid due to existing link' do
|
||||
let(:source) { issue }
|
||||
let(:target) { task }
|
||||
end
|
||||
|
||||
it_behaves_like 'invalid due to existing link' do
|
||||
let(:source) { task }
|
||||
let(:target) { issue }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for existing issuable link with existing parent link' do
|
||||
let(:link) { build(link_factory, source_id: source.id, target_id: target.id) }
|
||||
|
||||
before do
|
||||
create(:parent_link, work_item_parent: issue, work_item: task)
|
||||
link.save!(validate: false)
|
||||
end
|
||||
|
||||
context 'when source is issue' do
|
||||
let(:source) { issue }
|
||||
let(:target) { task }
|
||||
|
||||
it 'is valid' do
|
||||
expect(link).to be_valid
|
||||
expect(link.errors).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source is task' do
|
||||
let(:source) { task }
|
||||
let(:target) { issue }
|
||||
|
||||
it 'is valid' do
|
||||
expect(link).to be_valid
|
||||
expect(link.errors).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ RSpec.describe 'gitlab:shell rake tasks', :silence_stdout do
|
|||
describe 'install task' do
|
||||
it 'installs and compiles gitlab-shell' do
|
||||
expect_any_instance_of(Gitlab::TaskHelpers).to receive(:checkout_or_clone_version)
|
||||
allow(Kernel).to receive(:system).with('bin/install').and_return(true)
|
||||
allow(Kernel).to receive(:system).with('make', 'build').and_return(true)
|
||||
allow(Kernel).to receive(:system).with('make', 'make_necessary_dirs', 'build').and_return(true)
|
||||
|
||||
run_rake_task('gitlab:shell:install')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -652,6 +652,46 @@ RSpec.describe ApplicationWorker, feature_category: :shared do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' do
|
||||
let(:worker) { ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper }
|
||||
|
||||
context 'when calling perform_async with setter' do
|
||||
subject(:operation) { worker.set(testing: true).perform_async({ 'job_class' => ActionMailer::MailDeliveryJob }) }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
|
||||
context 'when calling perform_async with setter without job_class' do
|
||||
subject(:operation) { worker.set(testing: true).perform_async }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
|
||||
context 'when calling perform_in with setter' do
|
||||
subject(:operation) { worker.set(testing: true).perform_in(1, { 'job_class' => ActionMailer::MailDeliveryJob }) }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
|
||||
context 'when calling perform_in with setter without job_class' do
|
||||
subject(:operation) { worker.set(testing: true).perform_in(1) }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
|
||||
context 'when calling perform_at with setter' do
|
||||
subject(:operation) { worker.set(testing: true).perform_at(1, { 'job_class' => ActionMailer::MailDeliveryJob }) }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
|
||||
context 'when calling perform_at with setter without job_class' do
|
||||
subject(:operation) { worker.set(testing: true).perform_at(1) }
|
||||
|
||||
it_behaves_like 'uses shard router'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when calling perform_async with setter' do
|
||||
subject(:operation) { worker.set(testing: true).perform_async }
|
||||
|
||||
|
|
|
|||
|
|
@ -1310,10 +1310,10 @@
|
|||
core-js "^3.29.1"
|
||||
mitt "^3.0.1"
|
||||
|
||||
"@gitlab/eslint-plugin@19.6.1":
|
||||
version "19.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-19.6.1.tgz#1e59cb0d83e2f8522945b1b5f01d1fc284b7e729"
|
||||
integrity sha512-VA5eH9U6qr3PH24/hhwNKS4AF3jPB78ZaBmuQipGsn0DlyOqOdg2JnuX7C5tR4yM1D7uK2FcAdrW4AGovEQ7Xw==
|
||||
"@gitlab/eslint-plugin@20.0.0":
|
||||
version "20.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-20.0.0.tgz#d451169692b3ee51e7e946f6b9cead3de5132a51"
|
||||
integrity sha512-D/nScJCBqR5TMJkg5jpanhTIvrRVsWPohPUUhkHmCrjyXDjjZdZ3hkLZBF66tst0yENFDh6l5mtRVCzCIU5xdA==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "^7.14.1"
|
||||
eslint-config-airbnb-base "^15.0.0"
|
||||
|
|
|
|||