Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-31 06:09:17 +00:00
parent 226c5810c9
commit a9f214d421
18 changed files with 198 additions and 22 deletions

View file

@ -117,6 +117,7 @@ export default {
'autocompleteAwardEmojisPath',
'calendarPath',
'canBulkUpdate',
'canCreateProjects',
'canReadCrmContact',
'canReadCrmOrganization',
'emptyStateSvgPath',
@ -136,6 +137,7 @@ export default {
'isSignedIn',
'jiraIntegrationPath',
'newIssuePath',
'newProjectPath',
'releasesPath',
'rssPath',
'showNewIssueLink',
@ -844,12 +846,17 @@ export default {
</issuable-list>
<template v-else-if="isSignedIn">
<gl-empty-state
:description="$options.i18n.noIssuesSignedInDescription"
:title="$options.i18n.noIssuesSignedInTitle"
:svg-path="emptyStateSvgPath"
>
<gl-empty-state :title="$options.i18n.noIssuesSignedInTitle" :svg-path="emptyStateSvgPath">
<template #description>
<p>{{ $options.i18n.noIssuesSignedInDescription }}</p>
<p v-if="canCreateProjects">
<strong>{{ $options.i18n.noGroupIssuesSignedInDescription }}</strong>
</p>
</template>
<template #actions>
<gl-button v-if="canCreateProjects" :href="newProjectPath" variant="confirm">
{{ $options.i18n.newProjectLabel }}
</gl-button>
<gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm">
{{ $options.i18n.newIssueLabel }}
</gl-button>

View file

@ -29,7 +29,11 @@ export const i18n = {
jiraIntegrationSecondaryMessage: s__('JiraService|This feature requires a Premium plan.'),
jiraIntegrationTitle: s__('JiraService|Using Jira for issue tracking?'),
newIssueLabel: __('New issue'),
newProjectLabel: __('New project'),
noClosedIssuesTitle: __('There are no closed issues'),
noGroupIssuesSignedInDescription: __(
'Issues exist in projects, so to create an issue, first create a project.',
),
noOpenIssuesDescription: __('To keep this project going, create a new issue'),
noOpenIssuesTitle: __('There are no open issues'),
noIssuesSignedInDescription: __(

View file

@ -80,6 +80,7 @@ export function mountIssuesListApp() {
autocompleteAwardEmojisPath,
calendarPath,
canBulkUpdate,
canCreateProjects,
canEdit,
canImportIssues,
canReadCrmContact,
@ -109,6 +110,7 @@ export function mountIssuesListApp() {
markdownHelpPath,
maxAttachmentSize,
newIssuePath,
newProjectPath,
projectImportJiraPath,
quickActionsHelpPath,
releasesPath,
@ -133,6 +135,7 @@ export function mountIssuesListApp() {
autocompleteAwardEmojisPath,
calendarPath,
canBulkUpdate: parseBoolean(canBulkUpdate),
canCreateProjects: parseBoolean(canCreateProjects),
canReadCrmContact: parseBoolean(canReadCrmContact),
canReadCrmOrganization: parseBoolean(canReadCrmOrganization),
emptyStateSvgPath,
@ -153,6 +156,7 @@ export function mountIssuesListApp() {
isSignedIn: parseBoolean(isSignedIn),
jiraIntegrationPath,
newIssuePath,
newProjectPath,
releasesPath,
rssPath,
showNewIssueLink: parseBoolean(showNewIssueLink),

View file

@ -238,10 +238,12 @@ module IssuesHelper
def group_issues_list_data(group, current_user)
common_issues_list_data(group, current_user).merge(
can_create_projects: can?(current_user, :create_projects, group).to_s,
can_read_crm_contact: can?(current_user, :read_crm_contact, group).to_s,
can_read_crm_organization: can?(current_user, :read_crm_organization, group).to_s,
has_any_issues: @has_issues.to_s,
has_any_projects: @has_projects.to_s
has_any_projects: @has_projects.to_s,
new_project_path: new_project_path(namespace_id: group.id)
)
end

View file

@ -56,8 +56,7 @@ class DiffFileEntity < DiffFileBaseEntity
# Used for inline diffs
expose :highlighted_diff_lines, using: DiffLineEntity, if: -> (diff_file, options) { inline_diff_view?(options) && diff_file.text? } do |diff_file|
file = conflict_file(options, diff_file) || diff_file
file.diff_lines_for_serializer
highlighted_diff_lines_for(diff_file, options)
end
expose :is_fully_expanded do |diff_file|
@ -89,6 +88,15 @@ class DiffFileEntity < DiffFileBaseEntity
# If nothing is present, inline will be the default.
options.fetch(:diff_view, :inline).to_sym
end
def highlighted_diff_lines_for(diff_file, options)
file = conflict_file(options, diff_file) || diff_file
file.diff_lines_for_serializer
rescue Gitlab::Git::Conflict::Parser::UnmergeableFile
# Fallback to diff_file as it means that conflict lines can't be parsed due to limit
diff_file.diff_lines_for_serializer
end
end
DiffFileEntity.prepend_mod

View file

@ -55,7 +55,10 @@ module AutoMerge
def available_for?(merge_request)
strong_memoize("available_for_#{merge_request.id}") do
merge_request.can_be_merged_by?(current_user) &&
merge_request.mergeable_state?(skip_ci_check: true) &&
merge_request.open? &&
!merge_request.broken? &&
!merge_request.draft? &&
merge_request.mergeable_discussions_state? &&
yield
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
class CleanupBackfillIntegrationsEnableSslVerification < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
MIGRATION = 'BackfillIntegrationsEnableSslVerification'
def up
finalize_background_migration(MIGRATION)
end
def down
# no-op
end
end

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class DropTemporaryIndexForBackfillIntegrationsEnableSslVerification < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
INDEX_NAME = 'tmp_index_integrations_on_id_where_type_droneci_or_teamcity'
INDEX_CONDITION = "type_new IN ('Integrations::DroneCi', 'Integrations::Teamcity') " \
"AND encrypted_properties IS NOT NULL"
def up
remove_concurrent_index_by_name :integrations, INDEX_NAME
end
def down
# this index is used in 20220209121435_backfill_integrations_enable_ssl_verification
add_concurrent_index :integrations, :id, where: INDEX_CONDITION, name: INDEX_NAME
end
end

View file

@ -0,0 +1 @@
fe0e9acc39c2408853ea3fc35574c553172ad381a5b6f243578f44ed77dc75f8

View file

@ -0,0 +1 @@
f34c6e7b75d375342f5c88a9c7b98e15031a6dcdadf7e7dad862ef5f32a54e68

View file

@ -29975,8 +29975,6 @@ CREATE INDEX tmp_index_for_null_project_namespace_id ON projects USING btree (id
CREATE INDEX tmp_index_for_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
CREATE INDEX tmp_index_integrations_on_id_where_type_droneci_or_teamcity ON integrations USING btree (id) WHERE ((type_new = ANY (ARRAY['Integrations::DroneCi'::text, 'Integrations::Teamcity'::text])) AND (encrypted_properties IS NOT NULL));
CREATE INDEX tmp_index_issues_on_issue_type_and_id ON issues USING btree (issue_type, id);
CREATE INDEX tmp_index_members_on_state ON members USING btree (state) WHERE (state = 2);

View file

@ -175,6 +175,8 @@ To configure streaming audit events for Git operations, see [Add a new event str
### Headers
> `X-Gitlab-Audit-Event-Type` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86881) in GitLab 15.0.
Headers are formatted as follows:
```plaintext
@ -182,6 +184,7 @@ POST /logs HTTP/1.1
Host: <DESTINATION_HOST>
Content-Type: application/x-www-form-urlencoded
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
X-Gitlab-Audit-Event-Type: repository_git_operation
```
### Example payloads for SSH events
@ -212,7 +215,8 @@ Fetch:
"target_details": "example-project",
"created_at": "2022-02-23T06:21:05.283Z",
"target_type": "Project",
"target_id": 29
"target_id": 29,
"event_type": "repository_git_operation"
}
```
@ -242,7 +246,8 @@ Push:
"target_details": "example-project",
"created_at": "2022-02-23T06:23:08.746Z",
"target_type": "Project",
"target_id": 29
"target_id": 29,
"event_type": "repository_git_operation"
}
```
@ -274,7 +279,8 @@ Fetch:
"target_details": "example-project",
"created_at": "2022-02-23T06:25:43.938Z",
"target_type": "Project",
"target_id": 29
"target_id": 29,
"event_type": "repository_git_operation"
}
```
@ -304,7 +310,8 @@ Push:
"target_details": "example-project",
"created_at": "2022-02-23T06:26:29.294Z",
"target_type": "Project",
"target_id": 29
"target_id": 29,
"event_type": "repository_git_operation"
}
```
@ -333,7 +340,8 @@ Fetch:
"target_details": "example-group/example-project",
"created_at": "2022-02-23T06:27:17.873Z",
"target_type": "Project",
"target_id": 29
"target_id": 29,
"event_type": "repository_git_operation"
}
```
@ -352,6 +360,7 @@ POST /logs HTTP/1.1
Host: <DESTINATION_HOST>
Content-Type: application/x-www-form-urlencoded
X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
X-Gitlab-Audit-Event-Type: audit_operation
```
### Example payload
@ -377,6 +386,7 @@ X-Gitlab-Event-Streaming-Token: <DESTINATION_TOKEN>
"target_details": "merge request title",
"created_at": "2022-03-09T06:53:11.181Z",
"target_type": "MergeRequest",
"target_id": 20
"target_id": 20,
"event_type": "audit_operation"
}
```

View file

@ -21324,6 +21324,9 @@ msgstr ""
msgid "Issues closed"
msgstr ""
msgid "Issues exist in projects, so to create an issue, first create a project."
msgstr ""
msgid "Issues must match this scope to appear in this list."
msgstr ""

View file

@ -1,7 +1,10 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Create' do
RSpec.describe 'Create', quarantine: {
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/363807',
type: :stale
} do
describe 'Create a new merge request' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|

View file

@ -67,6 +67,7 @@ describe('CE IssuesListApp component', () => {
autocompleteAwardEmojisPath: 'autocomplete/award/emojis/path',
calendarPath: 'calendar/path',
canBulkUpdate: false,
canCreateProjects: false,
canReadCrmContact: false,
canReadCrmOrganization: false,
emptyStateSvgPath: 'empty-state.svg',
@ -88,6 +89,7 @@ describe('CE IssuesListApp component', () => {
isSignedIn: true,
jiraIntegrationPath: 'jira/integration/path',
newIssuePath: 'new/issue/path',
newProjectPath: 'new/project/path',
releasesPath: 'releases/path',
rssPath: 'rss/path',
showNewIssueLink: true,
@ -118,6 +120,7 @@ describe('CE IssuesListApp component', () => {
issuesQueryResponse = jest.fn().mockResolvedValue(defaultQueryResponse),
issuesCountsQueryResponse = jest.fn().mockResolvedValue(getIssuesCountsQueryResponse),
sortPreferenceMutationResponse = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse),
stubs = {},
mountFn = shallowMount,
} = {}) => {
const requestHandlers = [
@ -136,6 +139,7 @@ describe('CE IssuesListApp component', () => {
data() {
return data;
},
stubs,
});
};
@ -521,10 +525,12 @@ describe('CE IssuesListApp component', () => {
it('shows empty state', () => {
expect(findGlEmptyState().props()).toMatchObject({
description: IssuesListApp.i18n.noIssuesSignedInDescription,
title: IssuesListApp.i18n.noIssuesSignedInTitle,
svgPath: defaultProvide.emptyStateSvgPath,
});
expect(findGlEmptyState().text()).toContain(
IssuesListApp.i18n.noIssuesSignedInDescription,
);
});
it('shows "New issue" and import/export buttons', () => {
@ -538,11 +544,11 @@ describe('CE IssuesListApp component', () => {
it('shows Jira integration information', () => {
const paragraphs = wrapper.findAll('p');
expect(paragraphs.at(1).text()).toContain(IssuesListApp.i18n.jiraIntegrationTitle);
expect(paragraphs.at(2).text()).toContain(
expect(paragraphs.at(2).text()).toContain(IssuesListApp.i18n.jiraIntegrationTitle);
expect(paragraphs.at(3).text()).toContain(
'Enable the Jira integration to view your Jira issues in GitLab.',
);
expect(paragraphs.at(3).text()).toContain(
expect(paragraphs.at(4).text()).toContain(
IssuesListApp.i18n.jiraIntegrationSecondaryMessage,
);
expect(findGlLink().text()).toBe('Enable the Jira integration');
@ -550,6 +556,29 @@ describe('CE IssuesListApp component', () => {
});
});
describe('when user is logged in and can create projects', () => {
beforeEach(() => {
wrapper = mountComponent({
provide: { canCreateProjects: true, hasAnyIssues: false, isSignedIn: true },
stubs: { GlEmptyState },
});
});
it('shows empty state with additional description about creating projects', () => {
expect(findGlEmptyState().text()).toContain(
IssuesListApp.i18n.noIssuesSignedInDescription,
);
expect(findGlEmptyState().text()).toContain(
IssuesListApp.i18n.noGroupIssuesSignedInDescription,
);
});
it('shows "New project" button', () => {
expect(findGlButton().text()).toBe(IssuesListApp.i18n.newProjectLabel);
expect(findGlButton().attributes('href')).toBe(defaultProvide.newProjectPath);
});
});
describe('when user is logged out', () => {
beforeEach(() => {
wrapper = mountComponent({

View file

@ -355,12 +355,14 @@ RSpec.describe IssuesHelper do
expected = {
autocomplete_award_emojis_path: autocomplete_award_emojis_path,
calendar_path: '#',
can_create_projects: 'true',
empty_state_svg_path: '#',
full_path: group.full_path,
has_any_issues: false.to_s,
has_any_projects: true.to_s,
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
new_project_path: new_project_path(namespace_id: group.id),
rss_path: '#',
sign_in_path: new_user_session_path
}

View file

@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe CleanupBackfillIntegrationsEnableSslVerification, :migration do
let(:job_class_name) { 'BackfillIntegrationsEnableSslVerification' }
before do
# Jobs enqueued in Sidekiq.
Sidekiq::Testing.disable! do
BackgroundMigrationWorker.perform_in(10, job_class_name, [1, 2])
BackgroundMigrationWorker.perform_in(20, job_class_name, [3, 4])
end
# Jobs tracked in the database.
Gitlab::Database::BackgroundMigrationJob.create!(
class_name: job_class_name,
arguments: [5, 6],
status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']
)
Gitlab::Database::BackgroundMigrationJob.create!(
class_name: job_class_name,
arguments: [7, 8],
status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']
)
migrate!
end
it_behaves_like(
'finalized tracked background migration',
Gitlab::BackgroundMigration::BackfillIntegrationsEnableSslVerification
)
end

View file

@ -91,5 +91,38 @@ RSpec.describe DiffFileEntity do
end
end
describe '#highlighted_diff_lines' do
context 'file without a conflict' do
let(:options) { { conflicts: {} } }
it 'calls diff_lines_for_serializer on diff_file' do
# #diff_lines_for_serializer gets called in #fully_expanded? as well so we expect twice
expect(diff_file).to receive(:diff_lines_for_serializer).twice.and_return([])
expect(subject[:highlighted_diff_lines]).to eq([])
end
end
context 'file with a conflict' do
let(:conflict_file) { instance_double(Gitlab::Conflict::File, conflict_type: :both_modified) }
let(:options) { { conflicts: { diff_file.new_path => conflict_file } } }
it 'calls diff_lines_for_serializer on matching conflict file' do
expect(conflict_file).to receive(:diff_lines_for_serializer).and_return([])
expect(subject[:highlighted_diff_lines]).to eq([])
end
context 'when Gitlab::Git::Conflict::Parser::UnmergeableFile gets raised' do
before do
allow(conflict_file).to receive(:diff_lines_for_serializer).and_raise(Gitlab::Git::Conflict::Parser::UnmergeableFile)
end
it 'falls back to diff_file diff_lines_for_serializer' do
expect(diff_file).to receive(:diff_lines_for_serializer).and_return([])
expect(subject[:highlighted_diff_lines]).to eq([])
end
end
end
end
it_behaves_like 'diff file with conflict_type'
end