Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-11-29 12:14:14 +00:00
parent 3396d8eca0
commit fb28ad5316
33 changed files with 331 additions and 26 deletions

View File

@ -3734,7 +3734,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'

View File

@ -1739,7 +1739,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
- 'spec/lib/gitlab/email/handler_spec.rb'

View File

@ -3337,7 +3337,6 @@ RSpec/FeatureCategory:
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'

View File

@ -45,7 +45,12 @@ module Ci
has_one :pending_state, class_name: 'Ci::BuildPendingState', foreign_key: :build_id, inverse_of: :build
has_one :queuing_entry, class_name: 'Ci::PendingBuild', foreign_key: :build_id, inverse_of: :build
has_one :runtime_metadata, class_name: 'Ci::RunningBuild', foreign_key: :build_id, inverse_of: :build
has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id, inverse_of: :build
has_many :trace_chunks,
->(build) { in_partition(build) },
class_name: 'Ci::BuildTraceChunk',
foreign_key: :build_id,
inverse_of: :build,
partition_foreign_key: :partition_id
has_many :report_results, class_name: 'Ci::BuildReportResult', foreign_key: :build_id, inverse_of: :build
has_one :namespace, through: :project
@ -55,7 +60,12 @@ module Ci
# Details: https://gitlab.com/gitlab-org/gitlab/-/issues/24644#note_689472685
has_many :job_artifacts, class_name: 'Ci::JobArtifact', foreign_key: :job_id, dependent: :destroy, inverse_of: :job # rubocop:disable Cop/ActiveRecordDependent
has_many :job_variables, class_name: 'Ci::JobVariable', foreign_key: :job_id, inverse_of: :job
has_many :job_annotations, class_name: 'Ci::JobAnnotation', foreign_key: :job_id, inverse_of: :job
has_many :job_annotations,
->(build) { in_partition(build) },
class_name: 'Ci::JobAnnotation',
foreign_key: :job_id,
partition_foreign_key: :partition_id,
inverse_of: :job
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_job_id, inverse_of: :build
has_many :pages_deployments, foreign_key: :ci_build_id, inverse_of: :ci_build
@ -64,7 +74,12 @@ module Ci
has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', foreign_key: :job_id, inverse_of: :job
end
has_one :runner_manager_build, class_name: 'Ci::RunnerManagerBuild', foreign_key: :build_id, inverse_of: :build,
has_one :runner_manager_build,
->(build) { in_partition(build) },
class_name: 'Ci::RunnerManagerBuild',
foreign_key: :build_id,
inverse_of: :build,
partition_foreign_key: :partition_id,
autosave: true
has_one :runner_manager, foreign_key: :runner_machine_id, through: :runner_manager_build, class_name: 'Ci::RunnerManager'

View File

@ -3,7 +3,12 @@
class Ci::BuildPendingState < Ci::ApplicationRecord
include Ci::Partitionable
belongs_to :build, class_name: 'Ci::Build', foreign_key: :build_id, inverse_of: :pending_state
belongs_to :build,
->(pending_state) { in_partition(pending_state) },
class_name: 'Ci::Build',
foreign_key: :build_id,
partition_foreign_key: :partition_id,
inverse_of: :pending_state
partitionable scope: :build

View File

@ -9,7 +9,12 @@ module Ci
include ::Gitlab::ExclusiveLeaseHelpers
include ::Gitlab::OptimisticLocking
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id, inverse_of: :trace_chunks
belongs_to :build,
->(trace_chunks) { in_partition(trace_chunks) },
class_name: 'Ci::Build',
foreign_key: :build_id,
partition_foreign_key: :partition_id,
inverse_of: :trace_chunks
partitionable scope: :build

View File

@ -168,6 +168,7 @@ module Ci
def ensure_pending_state
build_state = Ci::BuildPendingState.safe_find_or_create_by(
build_id: build.id,
partition_id: build.partition_id,
state: params.fetch(:state),
trace_checksum: trace_checksum,
trace_bytesize: trace_bytesize,

View File

@ -2712,6 +2712,15 @@
:weight: 1
:idempotent: true
:tags: []
- :name: ci_low_urgency_cancel_redundant_pipelines
:worker_name: Ci::LowUrgencyCancelRedundantPipelinesWorker
:feature_category: :continuous_integration
:has_external_dependencies: false
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: ci_parse_secure_file_metadata
:worker_name: Ci::ParseSecureFileMetadataWorker
:feature_category: :mobile_devops

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Ci
# Scheduled pipelines rarely cancel other pipelines and we don't need to
# use high urgency
class LowUrgencyCancelRedundantPipelinesWorker < CancelRedundantPipelinesWorker
urgency :low
idempotent!
end
end

View File

@ -165,6 +165,8 @@
- 1
- - ci_llm_generate_config
- 1
- - ci_low_urgency_cancel_redundant_pipelines
- 1
- - ci_parse_secure_file_metadata
- 1
- - ci_runners_process_runner_version_update

View File

@ -1,5 +1,9 @@
# frozen_string_literal: true
# This is noisy for draft MRs, so let's ignore this cop in draft mode since we have
# rubocop watching this as well.
return if helper.draft_mr?
# Danger should not comment when inline disables are added in the following files.
no_suggestions_for_extensions = %w[.md]

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class AddReopenIssueOnExternalParticipantNoteToServiceDeskSettings < Gitlab::Database::Migration[2.2]
milestone '16.7'
enable_lock_retries!
def change
add_column :service_desk_settings, :reopen_issue_on_external_participant_note, :boolean, null: false, default: false
end
end

View File

@ -0,0 +1 @@
b05062e183719785e3d1313c4f1f59fce8b19c8f86ddb0ba53abcde96cb4ca03

View File

@ -23520,6 +23520,7 @@ CREATE TABLE service_desk_settings (
custom_email text,
service_desk_enabled boolean DEFAULT true NOT NULL,
add_external_participants_from_cc boolean DEFAULT false NOT NULL,
reopen_issue_on_external_participant_note boolean DEFAULT false NOT NULL,
CONSTRAINT check_57a79552e1 CHECK ((char_length(custom_email) <= 255))
);

View File

@ -184,10 +184,10 @@ are available:
| Urgency | Duration in seconds | Notes |
|------------|---------------------|-----------------------------------------------|
| `:high` | 0.25s | |
| `:medium` | 0.5s | |
| `:default` | 1s | The default when nothing is specified. |
| `:low` | 5s | |
| `:high` | [0.25s](https://gitlab.com/gitlab-org/gitlab/-/blob/2f7a38fe48934b78f04233c4d2c81cde88a06da7/lib/gitlab/endpoint_attributes/config.rb#L8) | |
| `:medium` | [0.5s](https://gitlab.com/gitlab-org/gitlab/-/blob/2f7a38fe48934b78f04233c4d2c81cde88a06da7/lib/gitlab/endpoint_attributes/config.rb#L9) | |
| `:default` | [1s](https://gitlab.com/gitlab-org/gitlab/-/blob/2f7a38fe48934b78f04233c4d2c81cde88a06da7/lib/gitlab/endpoint_attributes/config.rb#L10) | The default when nothing is specified. |
| `:low` | [5s](https://gitlab.com/gitlab-org/gitlab/-/blob/2f7a38fe48934b78f04233c4d2c81cde88a06da7/lib/gitlab/endpoint_attributes/config.rb#L11) | |
### Rails controller

View File

@ -277,6 +277,10 @@ declaring the subscription in `ee/lib/ee/gitlab/event_store.rb`.
Subscriptions are stored in memory when the Rails app is loaded and they are immediately frozen.
It's not possible to modify subscriptions at runtime.
NOTE:
Before creating a subscription, make sure that the worker is already deployed to GitLab.com as the
newly introduced workers are [not compatible with canary deployments](sidekiq/compatibility_across_updates.md#adding-new-workers).
### Conditional dispatch of events
A subscription can specify a condition when to accept an event:

View File

@ -46,6 +46,8 @@ For more information on:
gitlab_rails['omniauth_auto_link_saml_user'] = true
```
Only the GitLab account's primary email address is matched against the email in the SAML response.
Alternatively, a user can manually link their SAML identity to an existing GitLab
account by [enabling OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user).

View File

@ -31,7 +31,6 @@ Experimental features are:
- UX not finalized, might be just quick action access.
- Not announced in a release post.
- Can be promoted in the user interface through [discovery moments](https://design.gitlab.com/usability/feature-management#discovery-moments), if needed.
- Feedback issue to engage with team.
## Beta

View File

@ -218,6 +218,7 @@ panels:
For an overview of editing label filters in the configuration file, see [GitLab Value Streams Dashboard - Label filters demo](https://www.youtube.com/watch?v=4qDAHCxCfik).
Label filters are appended as query parameters to the URL of the drill-down report of each eligible metric and automatically applied.
If the comparison panel from the configuration file is enabled with `filter_labels`, the drill-down links inherit the labels from the panel filter.
## Dashboard metrics and drill-down reports

View File

@ -6,7 +6,11 @@ module Gitlab
module Chain
class CancelPendingPipelines < Chain::Base
def perform!
::Ci::CancelRedundantPipelinesWorker.perform_async(pipeline.id)
if pipeline.schedule?
::Ci::LowUrgencyCancelRedundantPipelinesWorker.perform_async(pipeline.id)
else
::Ci::CancelRedundantPipelinesWorker.perform_async(pipeline.id)
end
end
def break?

View File

@ -33,6 +33,8 @@ module Gitlab
record: create_note,
invalid_exception: InvalidNoteError,
record_name: 'comment')
reopen_issue_on_external_participant_note
end
def metrics_event
@ -71,6 +73,34 @@ module Gitlab
raise UserNotFoundError unless from_address && author.verified_email?(from_address)
end
def reopen_issue_on_external_participant_note
return unless noteable.closed?
return unless author == Users::Internal.support_bot
return unless project.service_desk_setting&.reopen_issue_on_external_participant_note?
::Notes::CreateService.new(
project,
Users::Internal.support_bot,
noteable: noteable,
note: build_reopen_message,
confidential: true
).execute
end
def build_reopen_message
translated_text = s_(
"ServiceDesk|This issue has been reopened because it received a new comment from an external participant."
)
"#{assignees_references} :wave: #{translated_text}\n/reopen".lstrip
end
def assignees_references
return unless noteable.assignees.any?
noteable.assignees.map(&:to_reference).join(' ')
end
end
end
end

View File

@ -44743,6 +44743,9 @@ msgstr ""
msgid "ServiceDesk|The verification email wasn't received in time. There is a 30 minutes timeframe for verification emails to appear in your instance's Service Desk. Make sure that you have set up email forwarding correctly."
msgstr ""
msgid "ServiceDesk|This issue has been reopened because it received a new comment from an external participant."
msgstr ""
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
msgstr ""

View File

@ -5,7 +5,7 @@ Contact: https://about.gitlab.com/security/disclosure/
Policy: https://hackerone.com/gitlab/
Acknowledgments: https://hackerone.com/gitlab/
Acknowledgments: https://hackerone.com/gitlab/thanks
Acknowledgments: https://about.gitlab.com/security/vulnerability-acknowledgements/
Canonical: https://gitlab.com/gitlab-org/gitlab/-/blob/master/security.txt
@ -13,4 +13,6 @@ Canonical: https://gitlab.com/gitlab-org/gitlab/-/blob/master/security.txt
Preferred-Languages: en
Hiring: https://about.gitlab.com/jobs/
Expires: 2023-07-31T00:00:00Z
Expires: 2024-12-31T00:00:00Z
# This file uses the format described at https://securitytxt.org/

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines, feature_category: :continuous_integration do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
let_it_be(:command) { Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user) }
let_it_be(:step) { described_class.new(pipeline, command) }
@ -17,5 +17,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CancelPendingPipelines, feature_cate
subject
end
context 'with scheduled pipelines' do
before do
pipeline.source = :schedule
end
it 'enqueues LowUrgencyCancelRedundantPipelinesWorker' do
expect(Ci::LowUrgencyCancelRedundantPipelinesWorker)
.to receive(:perform_async).with(pipeline.id)
subject
end
end
end
end

View File

@ -2,11 +2,11 @@
require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
RSpec.describe Gitlab::Email::Handler::CreateNoteHandler, feature_category: :shared do
include_context 'email shared context'
let_it_be(:user) { create(:user, email: 'jake@adventuretime.ooo') }
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be_with_reload(:user) { create(:user, email: 'jake@adventuretime.ooo') }
let_it_be(:project) { create(:project, :public, :repository) }
let(:noteable) { note.noteable }
let(:note) { create(:diff_note_on_merge_request, project: project) }
@ -133,14 +133,16 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
context 'mail key is in the References header' do
context 'when mail key is in the References header' do
let(:email_raw) { fixture_file('emails/reply_without_subaddressing_and_key_inside_references.eml') }
it_behaves_like 'an email that contains a mail key', 'References'
end
context 'mail key is in the References header with a comma' do
let(:email_raw) { fixture_file('emails/reply_without_subaddressing_and_key_inside_references_with_a_comma.eml') }
context 'when mail key is in the References header with a comma' do
let(:email_raw) do
fixture_file('emails/reply_without_subaddressing_and_key_inside_references_with_a_comma.eml')
end
it_behaves_like 'an email that contains a mail key', 'References'
end
@ -228,4 +230,96 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
end
end
context 'when issue is closed' do
let_it_be(:noteable) { create(:issue, :closed, :confidential, project: project) }
let_it_be(:note) { create(:note, noteable: noteable, project: project) }
let!(:sent_notification) do
allow(Gitlab::ServiceDesk).to receive(:enabled?).with(project: project).and_return(true)
SentNotification.record_note(note, Users::Internal.support_bot.id)
end
let(:reply_address) { "support+#{sent_notification.reply_key}@example.com" }
let(:reopen_note) { noteable.notes.last }
let(:email_raw) do
<<~EMAIL
From: from@example.com
To: #{reply_address}
Subject: Issue title
Issue description
EMAIL
end
before do
stub_incoming_email_setting(enabled: true, address: 'support+%{key}@example.com')
end
it 'does not reopen issue but adds external participants comment' do
# Only 1 from received email
expect { receiver.execute }.to change { noteable.notes.count }.by(1)
expect(noteable).to be_closed
end
context 'when reopen_issue_on_external_participant_note is true' do
shared_examples 'an automatically reopened issue' do
it 'reopens issue, adds external participants comment and reopen comment' do
# 1 from received email and 1 reopen comment
expect { receiver.execute }.to change { noteable.notes.count }.by(2)
expect(noteable.reset).to be_open
expect(reopen_note).to be_confidential
expect(reopen_note.author).to eq(Users::Internal.support_bot)
expect(reopen_note.note).to include(reopen_comment_body)
end
end
let!(:settings) do
create(:service_desk_setting, project: project, reopen_issue_on_external_participant_note: true)
end
let(:reopen_comment_body) do
s_(
"ServiceDesk|This issue has been reopened because it received a new comment from an external participant."
)
end
it_behaves_like 'an automatically reopened issue'
it 'does not contain an assignee mention' do
receiver.execute
expect(reopen_note.note).not_to include("@")
end
context 'when issue is assigned to a user' do
before do
noteable.update!(assignees: [user])
end
it_behaves_like 'an automatically reopened issue'
it 'contains an assignee mention' do
receiver.execute
expect(reopen_note.note).to include(user.to_reference)
end
end
context 'when issue is assigned to multiple users' do
let_it_be(:another_user) { create(:user) }
before do
noteable.update!(assignees: [user, another_user])
end
it_behaves_like 'an automatically reopened issue'
it 'contains two assignee mentions' do
receiver.execute
expect(reopen_note.note).to include(user.to_reference)
expect(reopen_note.note).to include(another_user.to_reference)
end
end
end
end
end

View File

@ -2,7 +2,7 @@
require "spec_helper"
RSpec.describe Gitlab::Git::Compare do
RSpec.describe Gitlab::Git::Compare, feature_category: :source_code_management do
let_it_be(:repository) { create(:project, :repository).repository.raw }
let(:compare) { described_class.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) }

View File

@ -196,5 +196,6 @@ build_service_desk_setting: # service_desk_setting
- encrypted_custom_email_smtp_password_iv
- custom_email_smtp_password
- add_external_participants_from_cc
- reopen_issue_on_external_participant_note
remapped_attributes:
project_key: service_desk_address

View File

@ -5994,7 +5994,6 @@
- './spec/lib/gitlab/email/failure_handler_spec.rb'
- './spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- './spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- './spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- './spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb'
- './spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- './spec/lib/gitlab/email/handler_spec.rb'

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::LowUrgencyCancelRedundantPipelinesWorker, feature_category: :continuous_integration do
it 'is labeled as low urgency' do
expect(described_class.get_urgency).to eq(:low)
end
end

View File

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"time"
@ -157,12 +158,32 @@ func (p *Injector) newUploadRequest(ctx context.Context, params *entryParams, or
func (p *Injector) unpackParams(sendData string) (*entryParams, error) {
var params entryParams
if err := p.Unpack(&params, sendData); err != nil {
return nil, fmt.Errorf("dependency proxy: unpack sendData: %v", err)
return nil, fmt.Errorf("dependency proxy: unpack sendData: %w", err)
}
if err := p.validateParams(params); err != nil {
return nil, fmt.Errorf("dependency proxy: invalid params: %w", err)
}
return &params, nil
}
func (p *Injector) validateParams(params entryParams) error {
var uploadMethod = params.UploadConfig.Method
if uploadMethod != "" && uploadMethod != http.MethodPost && uploadMethod != http.MethodPut {
return fmt.Errorf("invalid upload method %s", uploadMethod)
}
var uploadUrl = params.UploadConfig.Url
if uploadUrl != "" {
if _, err := url.ParseRequestURI(uploadUrl); err != nil {
return fmt.Errorf("invalid upload url %w", err)
}
}
return nil
}
func (p *Injector) uploadMethodFrom(params *entryParams) string {
if params.UploadConfig.Method != "" {
return params.UploadConfig.Method

View File

@ -261,6 +261,20 @@ func TestInvalidUploadConfiguration(t *testing.T) {
sendData map[string]interface{}
}{
{
desc: "with an invalid overriden method",
sendData: mergeMap(baseSendData, map[string]interface{}{
"UploadConfig": map[string]string{
"Method": "TEAPOT",
},
}),
}, {
desc: "with an invalid url",
sendData: mergeMap(baseSendData, map[string]interface{}{
"UploadConfig": map[string]string{
"Url": "invalid_url",
},
}),
}, {
desc: "with an invalid headers",
sendData: mergeMap(baseSendData, map[string]interface{}{
"UploadConfig": map[string]interface{}{

View File

@ -5,14 +5,23 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"sync"
"time"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/nginx"
)
const (
// matches the default size used in httputil.ReverseProxy
bufferPoolSize = 32 * 1024
)
var (
defaultTarget = helper.URLMustParse("http://localhost")
// pool is a buffer pool that is shared across all Proxy instances to maximize buffer reuse.
pool = newBufferPool()
)
type Proxy struct {
@ -46,6 +55,7 @@ func NewProxy(myURL *url.URL, version string, roundTripper http.RoundTripper, op
u.Path = ""
p.reverseProxy = httputil.NewSingleHostReverseProxy(&u)
p.reverseProxy.Transport = roundTripper
p.reverseProxy.BufferPool = pool
chainDirector(p.reverseProxy, func(r *http.Request) {
r.Header.Set("Gitlab-Workhorse", p.Version)
r.Header.Set("Gitlab-Workhorse-Proxy-Start", fmt.Sprintf("%d", time.Now().UnixNano()))
@ -104,3 +114,25 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
p.reverseProxy.ServeHTTP(w, r)
}
type bufferPool struct {
pool sync.Pool
}
func newBufferPool() *bufferPool {
return &bufferPool{
pool: sync.Pool{
New: func() any {
return make([]byte, bufferPoolSize)
},
},
}
}
func (bp *bufferPool) Get() []byte {
return bp.pool.Get().([]byte)
}
func (bp *bufferPool) Put(v []byte) {
bp.pool.Put(v) //lint:ignore SA6002 we either allocate manually to satisfy the linter or let the compiler allocate for us and silence the linter
}

View File

@ -0,0 +1,16 @@
package proxy
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBufferPool(t *testing.T) {
bp := newBufferPool()
b := bp.Get()
assert.Len(t, b, bufferPoolSize)
bp.Put(b) // just test that it doesn't panic or something like that
}