提交 645d157d 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 36497af2
......@@ -57,6 +57,10 @@ export default {
type: String,
required: true,
},
projectId: {
type: String,
required: true,
},
projectPath: {
type: String,
required: true,
......@@ -327,6 +331,7 @@ export default {
</gl-tabs>
<alert-sidebar
:project-path="projectPath"
:project-id="projectId"
:alert="alert"
:sidebar-collapsed="sidebarCollapsed"
@alert-refresh="alertRefresh"
......
......@@ -16,6 +16,10 @@ export default {
type: Boolean,
required: true,
},
projectId: {
type: String,
required: true,
},
projectPath: {
type: String,
required: true,
......@@ -49,6 +53,7 @@ export default {
/>
<sidebar-assignees
:project-path="projectPath"
:project-id="projectId"
:alert="alert"
:sidebar-collapsed="sidebarCollapsed"
@alert-refresh="$emit('alert-refresh')"
......
......@@ -38,6 +38,10 @@ export default {
SidebarAssignee,
},
props: {
projectId: {
type: String,
required: true,
},
projectPath: {
type: String,
required: true,
......@@ -128,7 +132,7 @@ export default {
per_page: 20,
active: true,
current_user: true,
project_id: gon?.current_project_id,
project_id: this.projectId,
},
})
.then(({ data }) => {
......
......@@ -8,7 +8,7 @@ Vue.use(VueApollo);
export default selector => {
const domEl = document.querySelector(selector);
const { alertId, projectPath, projectIssuesPath } = domEl.dataset;
const { alertId, projectPath, projectIssuesPath, projectId } = domEl.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
......@@ -39,6 +39,7 @@ export default selector => {
props: {
alertId,
projectPath,
projectId,
projectIssuesPath,
},
});
......
......@@ -106,6 +106,7 @@ export default {
errorPollTimeout: 0,
issueCreationInProgress: false,
isAlertVisible: false,
isStacktraceEmptyAlertVisible: true,
closedIssueId: null,
};
},
......@@ -167,6 +168,9 @@ export default {
resolveBtnLabel() {
return this.errorStatus !== errorStatus.RESOLVED ? __('Resolve') : __('Unresolve');
},
showEmptyStacktraceAlert() {
return !this.loadingStacktrace && !this.showStacktrace && this.isStacktraceEmptyAlertVisible;
},
},
watch: {
error(val) {
......@@ -254,6 +258,10 @@ export default {
</gl-sprintf>
</gl-alert>
<gl-alert v-if="showEmptyStacktraceAlert" @dismiss="isStacktraceEmptyAlertVisible = false">
{{ __('No stack trace for this error') }}
</gl-alert>
<div class="error-details-header d-flex py-2 justify-content-between">
<div
v-if="!loadingStacktrace && stacktrace"
......
......@@ -15,6 +15,7 @@ module Projects::AlertManagementHelper
{
'alert-id' => alert_id,
'project-path' => project.full_path,
'project-id' => project.id,
'project-issues-path' => project_issues_path(project)
}
end
......
- license = viewer.license
= icon('balance-scale fw')
= sprite_icon('scale', size: 16)
This project is licensed under the
= succeed '.' do
%strong= license.name
......
---
title: Show notification about empty stacktrace
merge_request: 34517
author:
type: added
---
title: Restrict alert assignee user search to current project in alert management details
merge_request: 34649
author:
type: fixed
......@@ -4819,6 +4819,11 @@ type Group {
"""
first: Int
"""
The ID of the Iteration to look up
"""
id: ID
"""
Returns the last _n_ elements from the list.
"""
......
......@@ -13275,6 +13275,16 @@
},
"defaultValue": null
},
{
"name": "id",
"description": "The ID of the Iteration to look up",
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null
},
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
......@@ -9,10 +9,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
Each security vulnerability in the [Vulnerability List](../dependency_list/index.md) has its own standalone
Each security vulnerability in the [Security Dashboard](../security_dashboard/index.md#project-security-dashboard) has its own standalone
page.
![Standalone vulnerability page](img/standalone_vulnerability_page_v12_10.png)
![Standalone vulnerability page](img/standalone_vulnerability_page_v13_1.png)
On the standalone vulnerability page, you can interact with the vulnerability in
several different ways:
......
......@@ -395,7 +395,7 @@ msgstr ""
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr ""
msgid "%{labelStart}Confidence:%{labelEnd} %{confidence}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr ""
msgid "%{labelStart}File:%{labelEnd} %{file}"
......@@ -413,6 +413,9 @@ msgstr ""
msgid "%{labelStart}Report Type:%{labelEnd} %{reportType}"
msgstr ""
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr ""
......@@ -6462,6 +6465,9 @@ msgstr ""
msgid "Could not find design."
msgstr ""
msgid "Could not find iteration"
msgstr ""
msgid "Could not remove the trigger."
msgstr ""
......@@ -15068,6 +15074,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
msgid "No stack trace for this error"
msgstr ""
msgid "No starrers matched your search"
msgstr ""
......
......@@ -356,7 +356,6 @@ module QA
module Issuable
autoload :New, 'qa/page/issuable/new'
autoload :Sidebar, 'qa/page/issuable/sidebar'
end
module Alert
......@@ -442,6 +441,7 @@ module QA
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
autoload :Sidebar, 'qa/page/component/issuable/sidebar'
end
module IssueBoard
......
# frozen_string_literal: true
module QA
module Page
module Component
module Issuable
module Sidebar
extend QA::Page::PageConcern
def self.included(base)
super
base.view 'app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue' do
element :avatar_image
end
base.view 'app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue' do
element :more_assignees_link
end
base.view 'app/helpers/dropdowns_helper.rb' do
element :dropdown_input_field
end
base.view 'app/views/shared/issuable/_sidebar.html.haml' do
element :assignee_block
element :dropdown_menu_labels
element :edit_link_labels
element :labels_block
element :milestone_block
element :milestone_link
end
end
def click_milestone_link
click_element(:milestone_link)
end
def has_assignee?(username)
page.within(element_selector_css(:assignee_block)) do
has_text?(username)
end
end
def has_avatar_image_count?(count)
wait_assignees_block_finish_loading do
all_elements(:avatar_image, count: count)
end
end
def has_label?(label)
within_element(:labels_block) do
!!has_element?(:label, label_name: label)
end
end
def has_milestone?(milestone_title)
within_element(:milestone_block) do
has_element?(:milestone_link, title: milestone_title)
end
end
def more_assignees_link
find_element(:more_assignees_link)
end
def select_labels_and_refresh(labels)
Support::Retrier.retry_until do
click_element(:edit_link_labels)
has_element?(:dropdown_menu_labels, text: labels.first)
end
labels.each do |label|
within_element(:dropdown_menu_labels, text: label) do
send_keys_to_element(:dropdown_input_field, [label, :enter])
end
end
click_element(:edit_link_labels)
labels.each do |label|
has_element?(:labels_block, text: label, wait: 0)
end
refresh
end
def text_of_labels_block
find_element(:labels_block)
end
def toggle_more_assignees_link
click_element(:more_assignees_link)
end
private
def wait_assignees_block_finish_loading
within_element(:assignee_block) do
wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
finished_loading_block?
yield
end
end
end
end
end
end
end
end
# frozen_string_literal: true
module QA
module Page
module Issuable
class Sidebar < Page::Base
view 'app/views/shared/issuable/_sidebar.html.haml' do
element :labels_block
element :milestone_block
element :milestone_link
end
def has_label?(label)
within_element(:labels_block) do
has_element?(:label, label_name: label)
end
end
def has_milestone?(milestone_title)
within_element(:milestone_block) do
has_element?(:milestone_link, title: milestone_title)
end
end
end
end
end
end
......@@ -5,6 +5,7 @@ module QA
module MergeRequest
class Show < Page::Base
include Page::Component::Note
include Page::Component::Issuable::Sidebar
view 'app/assets/javascripts/mr_tabs_popover/components/popover.vue' do
element :dismiss_popover_button
......@@ -64,11 +65,6 @@ module QA
element :new_diff_line
end
view 'app/views/shared/issuable/_sidebar.html.haml' do
element :assignee_block
element :labels_block
end
view 'app/views/projects/merge_requests/_mr_title.html.haml' do
element :edit_button
end
......@@ -178,18 +174,6 @@ module QA
has_element?(:merge_button)
end
def has_assignee?(username)
page.within(element_selector_css(:assignee_block)) do
has_text?(username)
end
end
def has_label?(label)
within_element(:labels_block) do
!!has_element?(:label, label_name: label)
end
end
def has_pipeline_status?(text)
# Pipelines can be slow, so we wait a bit longer than the usual 10 seconds
has_element?(:merge_request_pipeline_info_content, text: text, wait: 30)
......
......@@ -8,6 +8,7 @@ module QA
include Page::Component::Issuable::Common
include Page::Component::Note
include Page::Component::DesignManagement
include Page::Component::Issuable::Sidebar
view 'app/assets/javascripts/notes/components/comment_form.vue' do
element :comment_button
......@@ -23,45 +24,25 @@ module QA
element :noteable_note_item
end
view 'app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue' do
element :avatar_image
end
view 'app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue' do
element :more_assignees_link
end
view 'app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue' do
element :remove_related_issue_button
end
view 'app/helpers/dropdowns_helper.rb' do
element :dropdown_input_field
end
view 'app/views/shared/issuable/_close_reopen_button.html.haml' do
element :close_issue_button
element :reopen_issue_button
end
view 'app/views/shared/issuable/_sidebar.html.haml' do
element :assignee_block
element :labels_block
element :edit_link_labels
element :dropdown_menu_labels
element :milestone_link
end
view 'app/views/shared/notes/_form.html.haml' do
element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/issues/_tabs.html.haml' do
element :discussion_tab_link
element :discussion_tab_content
element :designs_tab_link
element :designs_tab_content
element :designs_tab_link
element :discussion_tab_content
element :discussion_tab_link
end
def click_discussion_tab
......@@ -74,10 +55,6 @@ module QA
active_element?(:designs_tab_content)
end
def click_milestone_link
click_element(:milestone_link)
end
def click_remove_related_issue_button
click_element(:remove_related_issue_button)
end
......@@ -100,20 +77,10 @@ module QA
click_element :comment_button
end
def has_avatar_image_count?(count)
wait_assignees_block_finish_loading do
all_elements(:avatar_image, count: count)
end
end
def has_comment?(comment_text)
has_element?(:noteable_note_item, text: comment_text, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
end
def more_assignees_link
find_element(:more_assignees_link)
end
def noteable_note_item
find_element(:noteable_note_item)
end
......@@ -130,35 +97,6 @@ module QA
select_filter_with_text('Show history only')
end
def select_labels_and_refresh(labels)
Support::Retrier.retry_until do
click_element(:edit_link_labels)
has_element?(:dropdown_menu_labels, text: labels.first)
end
labels.each do |label|
within_element(:dropdown_menu_labels, text: label) do
send_keys_to_element(:dropdown_input_field, [label, :enter])
end
end
click_element(:edit_link_labels)
labels.each do |label|
has_element?(:labels_block, text: label, wait: 0)
end
refresh
end
def text_of_labels_block
find_element(:labels_block)
end
def toggle_more_assignees_link
click_element(:more_assignees_link)
end
private
def select_filter_with_text(text)
......@@ -168,15 +106,6 @@ module QA
find_element(:filter_options, text: text).click
end
end
def wait_assignees_block_finish_loading
within_element(:assignee_block) do
wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
finished_loading_block?
yield
end
end
end
end
end
end
......
......@@ -62,12 +62,9 @@ module QA
Page::Project::Issue::Show.perform do |issue_page|
expect(issue_page).to have_comment(comment_text)
end
Page::Issuable::Sidebar.perform do |issuable|
expect(issuable).to have_label('enhancement')
expect(issuable).to have_label('help wanted')
expect(issuable).to have_label('good first issue')
expect(issue_page).to have_label('enhancement')
expect(issue_page).to have_label('help wanted')
expect(issue_page).to have_label('good first issue')
end
end
end
......@@ -91,9 +88,9 @@ module QA
expect(page).to have_content('[Review comment] Nice blank line.')
expect(page).to have_content('[Single diff comment] Much better without this line!')
Page::Issuable::Sidebar.perform do |issuable|
expect(issuable).to have_label('bug')
expect(issuable).to have_label('enhancement')
Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_label('bug')
expect(merge_request).to have_label('enhancement')
end
end
......
......@@ -53,10 +53,7 @@ module QA
expect(merge_request).to have_description(@merge_request_description)
expect(merge_request).to have_assignee(gitlab_account_username)
expect(merge_request).to have_label(label.title)
end
Page::Issuable::Sidebar.perform do |sidebar|
expect(sidebar).to have_milestone(milestone.title)
expect(merge_request).to have_milestone(milestone.title)
end
end
end
......
......@@ -119,12 +119,12 @@ function rspec_matched_tests() {
local test_file_count=$(wc -w "${matching_tests_file}" | awk {'print $1'})
if [[ "${test_file_count}" -gt "${test_file_count_threshold}" ]]; then
echo "There are more than ${test_file_count_threshold} FOSS test files matched,"
echo "This job is intentionally failed because there are more than ${test_file_count_threshold} FOSS test files matched,"
echo "which would take too long to run in this job."
echo "To reduce the likelihood of breaking FOSS pipelines,"
echo "please add [RUN AS-IF-FOSS] to the MR title and restart the pipeline."
echo "This would run all as-if-foss jobs in this merge request"
echo "and remove this job from the pipeline."
echo "and remove this failing job from the pipeline."
exit 1
fi
......
......@@ -13,6 +13,17 @@ templating:
options:
default_value: 'default'
text_variable_simple_syntax: 'default value'
custom_variable_simple_syntax: ['value1', 'value2', 'value3']
custom_variable_full_syntax:
label: 'Variable 2'
type: custom
options:
values:
- value: 'value option 1'
text: 'Option 1'
- value: 'value_option_2'
text: 'Option 2'
default: true
panel_groups:
- group: Group A
priority: 1
......
{
"type": "object",
"required": [
"type", "options"
],
"properties": {
"type": { "enum": ["custom"] },
"label": { "type": "string" },
"options": { "$ref": "custom_variable_options.json" }
},
"additionalProperties": false
}
{
"type": "object",
"required": ["values"],
"properties": {
"values": {
"type": "array",
"items": { "$ref": "custom_variable_values.json" }
}
},
"additionalProperties": false
}
{
"type": "object",
"required": ["value"],
"properties": {
"value": { "type": "string" },
"text": { "type": "string" },
"default": { "type": "boolean" }
},
"additionalProperties": false
}
......@@ -4,7 +4,7 @@
"type", "options"
],
"properties": {
"type": { "type": "string" },
"type": { "enum": ["text"] },
"label": { "type": "string" },
"options": { "$ref": "text_variable_options.json" }
},
......
......@@ -4,7 +4,12 @@
"^[a-zA-Z0-9_]*$": {
"anyOf": [
{ "$ref": "text_variable_full_syntax.json" },
{ "type": "string" }
{ "type": "string" },
{
"type": "array",
"items": { "type": "string" }
},
{ "$ref": "custom_variable_full_syntax.json" }
]
}
},
......
......@@ -19,6 +19,7 @@ describe('AlertDetails', () => {
let mock;
const projectPath = 'root/alerts';
const projectIssuesPath = 'root/alerts/-/issues';
const projectId = '1';
const findDetailsTable = () => wrapper.find(GlTable);
......@@ -28,6 +29,7 @@ describe('AlertDetails', () => {
alertId: 'alertId',
projectPath,
projectIssuesPath,
projectId,
},
data() {
return { alert: { ...mockAlert }, ...data };
......
......@@ -33,6 +33,7 @@ describe('Alert Details Sidebar Assignees', () => {
...data,
sidebarCollapsed,
projectPath: 'projectPath',
projectId: '1',
},
mocks: {
$apollo: {
......
......@@ -22,6 +22,7 @@ describe('Alert Details Sidebar', () => {
alert,
sidebarCollapsed,
projectPath: 'projectPath',
projectId: '1',
},
stubs,
});
......
......@@ -48,6 +48,7 @@ describe('ErrorDetails', () => {
const findUpdateResolveStatusButton = () =>
wrapper.find('[data-testid="update-resolve-status-btn"]');
const findExternalUrl = () => wrapper.find('[data-testid="external-url-link"]');
const findAlert = () => wrapper.find(GlAlert);
function mountComponent() {
wrapper = shallowMount(ErrorDetails, {
......@@ -278,15 +279,17 @@ describe('ErrorDetails', () => {
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
});
});
it('should NOT show stacktrace if no entries', () => {
it('should NOT show stacktrace if no entries and show Alert message', () => {
store.state.details.loadingStacktrace = false;
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(false);
expect(findAlert().text()).toBe('No stack trace for this error');
});
});
});
......@@ -404,7 +407,6 @@ describe('ErrorDetails', () => {
});
it('should show alert with closed issueId', () => {
const findAlert = () => wrapper.find(GlAlert);
const closedIssueId = 123;
wrapper.setData({
isAlertVisible: true,
......
......@@ -7,7 +7,8 @@ describe Projects::AlertManagementHelper do
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:project_path) { project.full_path }
let(:project_path) { project.full_path }
let(:project_id) { project.id }
describe '#alert_management_data' do
let(:user_can_enable_alert_management) { true }
......@@ -75,6 +76,7 @@ describe Projects::AlertManagementHelper do
expect(helper.alert_management_detail_data(project, alert_id)).to eq(
'alert-id' => alert_id,
'project-path' => project_path,
'project-id' => project_id,
'project-issues-path' => issues_path
)
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册