Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c2c0a76236
commit
979f91ad68
2
Gemfile
2
Gemfile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
18
Gemfile.lock
18
Gemfile.lock
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export default class GlFieldErrors {
|
|||
'input[type=url]',
|
||||
'input[type=number]',
|
||||
'textarea',
|
||||
'select',
|
||||
].join(',');
|
||||
|
||||
this.state.inputs = this.form
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:<script>alert(0)</script>"></input>
|
||||
</div>
|
||||
<div class="form-group"></div>
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue