Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-01-08 09:30:17 +00:00
parent c2c0a76236
commit 979f91ad68
20 changed files with 180 additions and 69 deletions

View File

@ -55,7 +55,7 @@ end
gem 'gitlab-backup-cli', path: 'gems/gitlab-backup-cli', require: 'gitlab/backup/cli', feature_category: :backup_restore
gem 'gitlab-secret_detection', '< 1.0', feature_category: :secret_detection
gem 'gitlab-secret_detection', path: 'gems/gitlab-secret_detection', feature_category: :secret_detection
# Responders respond_to and respond_with
gem 'responders', '~> 3.0' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -238,7 +238,6 @@
{"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"},
{"name":"gitlab-net-dns","version":"0.9.2","platform":"ruby","checksum":"f726d978479d43810819f12a45c0906d775a07e34df111bbe693fffbbef3059d"},
{"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"},
{"name":"gitlab-secret_detection","version":"0.14.2","platform":"ruby","checksum":"c6d3bc92b47cdf930ff7bf1e519a849353f33df1a2b4493078963769854850f0"},
{"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"},
{"name":"gitlab-styles","version":"13.0.2","platform":"ruby","checksum":"e662b9334643763b55a861f9e26091096547f98179bd89b0fa8d6c6fb8cec861"},
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},

View File

@ -105,6 +105,16 @@ PATH
diffy
pg_query
PATH
remote: gems/gitlab-secret_detection
specs:
gitlab-secret_detection (0.1.1)
grpc (= 1.63.0)
grpc-tools (= 1.63.0)
parallel (~> 1.22)
re2 (~> 2.4)
toml-rb (~> 2.2)
PATH
remote: gems/gitlab-utils
specs:
@ -772,12 +782,6 @@ GEM
activesupport (>= 5.2.0)
rake (~> 13.0)
snowplow-tracker (~> 0.8.0)
gitlab-secret_detection (0.14.2)
grpc (= 1.63.0)
grpc-tools (= 1.63.0)
parallel (~> 1.19)
re2 (= 2.7.0)
toml-rb (~> 2.2.0)
gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1)
activesupport (>= 6, < 8)
json_schemer (~> 2.3.0)
@ -2097,7 +2101,7 @@ DEPENDENCIES
gitlab-safe_request_store!
gitlab-schema-validation!
gitlab-sdk (~> 0.3.0)
gitlab-secret_detection (< 1.0)
gitlab-secret_detection!
gitlab-security_report_schemas (= 0.1.2.min15.0.0.max15.2.1)
gitlab-sidekiq-fetcher!
gitlab-styles (~> 13.0.2)

View File

@ -239,7 +239,6 @@
{"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"},
{"name":"gitlab-net-dns","version":"0.9.2","platform":"ruby","checksum":"f726d978479d43810819f12a45c0906d775a07e34df111bbe693fffbbef3059d"},
{"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"},
{"name":"gitlab-secret_detection","version":"0.14.2","platform":"ruby","checksum":"c6d3bc92b47cdf930ff7bf1e519a849353f33df1a2b4493078963769854850f0"},
{"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"},
{"name":"gitlab-styles","version":"13.0.2","platform":"ruby","checksum":"e662b9334643763b55a861f9e26091096547f98179bd89b0fa8d6c6fb8cec861"},
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},

View File

@ -105,6 +105,16 @@ PATH
diffy
pg_query
PATH
remote: gems/gitlab-secret_detection
specs:
gitlab-secret_detection (0.1.1)
grpc (= 1.63.0)
grpc-tools (= 1.63.0)
parallel (~> 1.22)
re2 (~> 2.4)
toml-rb (~> 2.2)
PATH
remote: gems/gitlab-utils
specs:
@ -785,12 +795,6 @@ GEM
activesupport (>= 5.2.0)
rake (~> 13.0)
snowplow-tracker (~> 0.8.0)
gitlab-secret_detection (0.14.2)
grpc (= 1.63.0)
grpc-tools (= 1.63.0)
parallel (~> 1.19)
re2 (= 2.7.0)
toml-rb (~> 2.2.0)
gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1)
activesupport (>= 6, < 8)
json_schemer (~> 2.3.0)
@ -2130,7 +2134,7 @@ DEPENDENCIES
gitlab-safe_request_store!
gitlab-schema-validation!
gitlab-sdk (~> 0.3.0)
gitlab-secret_detection (< 1.0)
gitlab-secret_detection!
gitlab-security_report_schemas (= 0.1.2.min15.0.0.max15.2.1)
gitlab-sidekiq-fetcher!
gitlab-styles (~> 13.0.2)

View File

@ -124,8 +124,8 @@ export default class GlFieldError {
// For UX, wait til after first invalid submission to check each keyup
// eslint-disable-next-line @gitlab/no-global-event-off
this.inputElement
.off('keyup.fieldValidator')
.on('keyup.fieldValidator', this.updateValidity.bind(this));
.off('input.fieldValidator')
.on('input.fieldValidator', this.updateValidity.bind(this));
}
/* Get or set current input value */

View File

@ -22,6 +22,7 @@ export default class GlFieldErrors {
'input[type=url]',
'input[type=number]',
'textarea',
'select',
].join(',');
this.state.inputs = this.form

View File

@ -44,7 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:ci_graphql_pipeline_mini_graph, project)
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
push_frontend_feature_flag(:vulnerability_code_flow, project)
push_frontend_feature_flag(:pipeline_vulnerability_code_flow, project)
push_frontend_feature_flag(:mr_vulnerability_code_flow, project)
push_frontend_feature_flag(:mr_show_reports_immediately, project)
end

View File

@ -24,7 +24,7 @@ class DiffNote < Note
validate :verify_supported, unless: :importing?
before_validation :set_line_code, if: :on_text?, unless: :importing?
after_save :keep_around_commits, if: -> { needs_keep_around_ref? }
after_save :keep_around_commits, unless: -> { importing? || skip_keep_around_commits }
NoteDiffFileCreationError = Class.new(StandardError)

View File

@ -59,6 +59,9 @@ class Note < ApplicationRecord
# Attribute used to store the status of quick actions.
attr_accessor :quick_actions_status
# Attribute used to determine whether keep_around_commits will be skipped for diff notes.
attr_accessor :skip_keep_around_commits
attribute :system, default: false
attr_spammable :note, spam_description: true
@ -185,7 +188,7 @@ class Note < ApplicationRecord
# Syncs `confidential` with `internal` as we rename the column.
# https://gitlab.com/gitlab-org/gitlab/-/issues/367923
before_create :set_internal_flag
after_save :keep_around_commit, if: :needs_keep_around_ref?
after_save :keep_around_commit, if: :for_project_noteable?, unless: -> { importing? || skip_keep_around_commits }
after_save :touch_noteable, unless: :importing?
after_commit :notify_after_create, on: :create
after_commit :notify_after_destroy, on: :destroy
@ -746,10 +749,6 @@ class Note < ApplicationRecord
!group_restriction || Ability.allowed?(user, group_restriction, project&.group)
end
def needs_keep_around_ref?
for_project_noteable? && !for_merge_request? && !importing?
end
def keep_around_commit
project.repository.keep_around(self.commit_id, source: "#{noteable_type}/#{self.class.name}")
end

View File

@ -40,11 +40,13 @@ module DraftNotes
draft_note,
executing_user,
skip_capture_diff_note_position: true,
skip_keep_around_commits: true,
skip_merge_status_trigger: true
)
end
capture_diff_note_positions(created_notes)
keep_around_commits(created_notes)
draft_notes.delete_all
notification_service.async.new_review(review)
todo_service.new_review(review, current_user)
@ -53,12 +55,13 @@ module DraftNotes
after_publish
end
def create_note_from_draft(draft, executing_user, skip_capture_diff_note_position: false, skip_merge_status_trigger: false)
def create_note_from_draft(draft, executing_user, skip_capture_diff_note_position: false, skip_keep_around_commits: false, skip_merge_status_trigger: false)
# Make sure the diff file is unfolded in order to find the correct line
# codes.
draft.diff_file&.unfold_diff_lines(draft.original_position)
note = Notes::CreateService.new(project, current_user, draft.publish_params).execute(
note_params = draft.publish_params.merge(skip_keep_around_commits: skip_keep_around_commits)
note = Notes::CreateService.new(project, current_user, note_params).execute(
skip_capture_diff_note_position: skip_capture_diff_note_position,
skip_merge_status_trigger: skip_merge_status_trigger,
executing_user: executing_user
@ -94,6 +97,18 @@ module DraftNotes
end
end
def keep_around_commits(notes)
shas = notes.flat_map do |note|
note.shas if note.diff_note?
end.uniq
# We are allowing this since gitaly call will be created for each sha and
# even though they're unique, there will still be multiple Gitaly calls.
Gitlab::GitalyClient.allow_n_plus_1_calls do
project.repository.keep_around(*shas, source: self.class.name)
end
end
def after_publish
merge_request.assignees.each do |assignee|
next unless assignee.merge_request_dashboard_enabled?

View File

@ -1,9 +0,0 @@
---
name: pipeline_vulnerability_code_flow
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458062
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159610
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/483039
milestone: '17.5'
group: group::security platform management
type: beta
default_enabled: true

View File

@ -26287,6 +26287,22 @@ Returns [`[VulnerableProjectsByGrade!]`](#vulnerableprojectsbygrade).
| <a id="groupvulnerabilitygradesincludesubgroups"></a>`includeSubgroups` | [`Boolean`](#boolean) | Include grades belonging to subgroups. |
| <a id="groupvulnerabilitygradeslettergrade"></a>`letterGrade` | [`VulnerabilityGrade`](#vulnerabilitygrade) | Filter the response by given letter grade. |
##### `Group.vulnerabilityIdentifierSearch`
Search for vulnerabilities by identifier. Feature flag `vulnerability_filtering_by_identifier_group` has to be enabled for the group.
DETAILS:
**Introduced** in GitLab 17.8.
**Status**: Experiment.
Returns [`[String!]`](#string).
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="groupvulnerabilityidentifiersearchname"></a>`name` | [`String!`](#string) | Search identifier by name. Substring or partial match search is supported and argument should be greater than 3 characters. |
##### `Group.vulnerabilityManagementPolicies`
Vulnerability Management Policies of the project.

View File

@ -163,12 +163,12 @@ The code flow information is shown the **Code flow** tab and includes:
The code flow view is integrated into each view where vulnerability details are shown.
On GitLab self-managed, you can activate the view by [enabling the required feature flags](../../../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) starting in the minimum version shown.
| Location | Availability on GitLab.com | Availability on GitLab self-managed | Feature flags required |
|-------------------------------------------------------------------|-----------------------------------|-----------------------------------------------------------------------|-----------------------------------------------------------------------|
| [Vulnerability Report](../vulnerability_report/index.md) | Enabled by default in GitLab 17.3 | Enabled by default in GitLab 17.6. Available in GitLab 17.3 or later. | `vulnerability_code_flow` |
| [Merge request widget](index.md#merge-request-widget) | Enabled by default in GitLab 17.6 | Enabled by default in GitLab 17.6. Available in GitLab 17.5 or later. | Both `vulnerability_code_flow` and `pipeline_vulnerability_code_flow` |
| [Pipeline security report](../vulnerability_report/pipeline.md) | Enabled by default in GitLab 17.6 | Enabled by default in GitLab 17.6. Available in GitLab 17.5 or later. | Both `vulnerability_code_flow` and `pipeline_vulnerability_code_flow` |
| [Merge request changes view](index.md#merge-request-changes-view) | Enabled by default in GitLab 17.7 | Enabled by default in GitLab 17.7. Available in GitLab 17.7 or later. | Both `vulnerability_code_flow` and `mr_vulnerability_code_flow` |
| Location | Availability on GitLab.com | Availability on GitLab self-managed | Feature flags required |
|-------------------------------------------------------------------|-----------------------------------|-----------------------------------------------------------------------|---------------------------------------------------------------------|
| [Vulnerability Report](../vulnerability_report/index.md) | Enabled by default in GitLab 17.3 | Enabled by default in GitLab 17.6. Available in GitLab 17.3 or later. | `vulnerability_code_flow` |
| [Merge request widget](index.md#merge-request-widget) | Enabled by default in GitLab 17.6 | Enabled by default in GitLab 17.6. Available in GitLab 17.5 or later. | `vulnerability_code_flow` |
| [Pipeline security report](../vulnerability_report/pipeline.md) | Enabled by default in GitLab 17.6 | Enabled by default in GitLab 17.6. Available in GitLab 17.5 or later. | `vulnerability_code_flow` |
| [Merge request changes view](index.md#merge-request-changes-view) | Enabled by default in GitLab 17.7 | Enabled by default in GitLab 17.7. Available in GitLab 17.7 or later. | Both `vulnerability_code_flow` and `mr_vulnerability_code_flow` |
## Troubleshooting

View File

@ -23,6 +23,8 @@ module API
expose :updated_at
def todo_target_class(target_type)
# Ensure the `Key` type properly maps to the `SSHKey` entity
target_type = "SSHKey" if target_type == "Key"
# false as second argument prevents looking up in module hierarchy
# see also https://gitlab.com/gitlab-org/gitlab-foss/issues/59719
::API::Entities.const_get(target_type, false)

View File

@ -21,6 +21,9 @@
<textarea required title="Textarea is required">Textarea</textarea>
</div>
<div class="form-group">
<select required><option value="">Select number</option><option value="1">1</option></select>
</div>
<div class="form-group">
<input type="text" title="xss:&lt;script&gt;alert(0)&lt;/script&gt;"></input>
</div>
<div class="form-group"></div>

View File

@ -28,7 +28,7 @@ describe('GL Style Field Errors', () => {
expect(testContext.fieldErrors).toBeDefined();
const { inputs } = testContext.fieldErrors.state;
expect(inputs.length).toBe(6);
expect(inputs.length).toBe(7);
});
it('should ignore elements with custom error handling', () => {
@ -45,9 +45,9 @@ describe('GL Style Field Errors', () => {
});
it('should not show any errors before submit attempt', () => {
testContext.$form.find('.email').val('not-a-valid-email').keyup();
testContext.$form.find('.text-required').val('').keyup();
testContext.$form.find('.alphanumberic').val('?---*').keyup();
testContext.$form.find('.email').val('not-a-valid-email').trigger('input');
testContext.$form.find('.required-text').val('').trigger('input');
testContext.$form.find('.alphanumberic').val('?---*').trigger('input');
const errorsShown = testContext.$form.find('.gl-field-error-outline');
@ -55,15 +55,15 @@ describe('GL Style Field Errors', () => {
});
it('should show errors when input valid is submitted', () => {
testContext.$form.find('.email').val('not-a-valid-email').keyup();
testContext.$form.find('.text-required').val('').keyup();
testContext.$form.find('.alphanumberic').val('?---*').keyup();
testContext.$form.find('.email').val('not-a-valid-email').trigger('input');
testContext.$form.find('.required-text').val('').trigger('input');
testContext.$form.find('.alphanumberic').val('?---*').trigger('input');
testContext.$form.submit();
const errorsShown = testContext.$form.find('.gl-field-error-outline');
expect(errorsShown.length).toBe(4);
expect(errorsShown.length).toBe(5);
});
it('should properly track validity state on input after invalid submission attempt', () => {
@ -79,41 +79,61 @@ describe('GL Style Field Errors', () => {
expect(fieldState.valid).toBe(false);
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
emailInputElement.val('not-a-valid-email').trigger('input');
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
emailInputElement.val('email@gitlab.com').trigger('input');
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
emailInputElement.val('not-a-valid-email').trigger('input');
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then empty input
emailInputElement.val('').keyup();
emailInputElement.val('').trigger('input');
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(true);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
emailInputElement.val('email@gitlab.com').trigger('input');
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
});
it('should properly track validity state on select input after invalid submission attempt', () => {
testContext.$form.submit();
const selectInputModel = testContext.fieldErrors.state.inputs[5];
const fieldState = selectInputModel.state;
const selectInputElement = selectInputModel.inputElement;
// No input
expect(selectInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(true);
expect(fieldState.valid).toBe(false);
// Then valid input
selectInputElement.val('1').trigger('input');
expect(selectInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
});
it('should properly infer error messages', () => {
testContext.$form.submit();
const trackedInputs = testContext.fieldErrors.state.inputs;
@ -130,7 +150,7 @@ describe('GL Style Field Errors', () => {
testContext.$form.submit();
const trackedInputs = testContext.fieldErrors.state.inputs;
const xssInput = trackedInputs[5];
const xssInput = trackedInputs[6];
const xssErrorElem = xssInput.inputElement.siblings('.gl-field-error');

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ::API::Entities::Todo, feature_category: :notifications do
using RSpec::Parameterized::TableSyntax
let(:todo) { build_stubbed(:todo) }
subject(:entity) { described_class.new(todo) }
describe '#todo_target_class' do
where(:type, :expected_entity) do
"Issue" | API::Entities::Issue
"Namespace" | API::Entities::Namespace
"Key" | API::Entities::SSHKey
end
with_them do
it "maps the type to the correct API entity" do
expect(entity.todo_target_class(type)).to be(expected_entity)
end
end
end
end

View File

@ -279,24 +279,20 @@ RSpec.describe Note, feature_category: :team_planning do
note.save!
end
it "skips #keep_around_commit if 'importing' is true" do
note = build(:note, project: noteable.project, noteable: noteable, importing: true)
it "skips #keep_around_commit if 'skip_keep_around_commits' is true" do
note = build(:note, project: noteable.project, noteable: noteable, skip_keep_around_commits: true)
expect(note).not_to receive(:keep_around_commit)
note.save!
end
describe 'on merge request' do
let!(:noteable) { create(:merge_request) }
it "skips #keep_around_commit if 'importing' is true" do
note = build(:note, project: noteable.project, noteable: noteable, importing: true)
it "skips #keep_around_commit" do
note = build(:note, project: noteable.project, noteable: noteable)
expect(note).not_to receive(:keep_around_commit)
expect(note).not_to receive(:keep_around_commit)
note.save!
end
note.save!
end
end

View File

@ -35,7 +35,8 @@ RSpec.describe DraftNotes::PublishService, feature_category: :code_review_workfl
end
it 'does not skip notification', :sidekiq_might_not_need_inline do
expect(Notes::CreateService).to receive(:new).with(project, user, drafts.first.publish_params).and_call_original
note_params = drafts.first.publish_params.merge(skip_keep_around_commits: false)
expect(Notes::CreateService).to receive(:new).with(project, user, note_params).and_call_original
expect_next_instance_of(NotificationService) do |notification_service|
expect(notification_service).to receive(:new_note)
end
@ -165,12 +166,17 @@ RSpec.describe DraftNotes::PublishService, feature_category: :code_review_workfl
publish
end
context 'capturing diff notes positions' do
context 'capturing diff notes positions and keeping around commits' do
before do
# Need to execute this to ensure that we'll be able to test creation of
# DiffNotePosition records as that only happens when the `MergeRequest#merge_ref_head`
# is present. This service creates that for the specified merge request.
MergeRequests::MergeToRefService.new(project: project, current_user: user).execute(merge_request)
# Need to re-stub this and call original as we are stubbing
# `Gitlab::Git::KeepAround#execute` in spec_helper for performance reason.
# Enabling it here so we can test the Gitaly calls it makes.
allow(Gitlab::Git::KeepAround).to receive(:execute).and_call_original
end
it 'creates diff_note_positions for diff notes' do
@ -180,6 +186,38 @@ RSpec.describe DraftNotes::PublishService, feature_category: :code_review_workfl
expect(notes.first.diff_note_positions).to be_any
expect(notes.last.diff_note_positions).to be_any
end
it 'keeps around the commits of each published note' do
publish
repository = project.repository
notes = merge_request.notes.order(id: :asc)
notes.first.shas.each do |sha|
expect(repository.ref_exists?("refs/keep-around/#{sha}")).to be_truthy
end
notes.last.shas.each do |sha|
expect(repository.ref_exists?("refs/keep-around/#{sha}")).to be_truthy
end
end
context 'checking gitaly calls' do
# NOTE: This was added to avoid test flakiness.
let(:merge_request) { create(:merge_request) }
it 'does not request a lot from Gitaly', :request_store, :clean_gitlab_redis_cache do
merge_request
position
Gitlab::GitalyClient.reset_counts
# NOTE: This should be reduced as we work on reducing Gitaly calls.
# Gitaly requests shouldn't go above this threshold as much as possible
# as it may add more to the Gitaly N+1 issue we are experiencing.
expect { publish }.to change { Gitlab::GitalyClient.get_request_count }.by(19)
end
end
end
context 'commit_id is set' do