Skip to content
Snippets Groups Projects
Unverified Commit 6bce855e authored by Samantha Ming's avatar Samantha Ming Committed by GitLab
Browse files

Merge branch '17-4-fix-vr-button' into '17-4-stable-ee'

Backport: Fixes issues with incorrectly displaying VR button

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166540



Merged-by: default avatarSamantha Ming <sming@gitlab.com>
Approved-by: default avatarSamantha Ming <sming@gitlab.com>
Approved-by: default avatarWill Meek <wmeek@gitlab.com>
Co-authored-by: default avatarMichael Becker <mbecker@gitlab.com>
parents 514e1432 23b04a21
No related branches found
No related tags found
No related merge requests found
Showing with 105 additions and 36 deletions
Loading
Loading
@@ -34154,6 +34154,7 @@ Represents a vulnerability.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="vulnerabilityairesolutionavailable"></a>`aiResolutionAvailable` | [`Boolean`](#boolean) | Indicates whether this type of vulnerability can be resolved with AI. |
| <a id="vulnerabilityairesolutionenabled"></a>`aiResolutionEnabled` | [`Boolean`](#boolean) | Indicates whether this specific vulnerability can be resolved with AI. |
| <a id="vulnerabilitycommenters"></a>`commenters` | [`UserCoreConnection!`](#usercoreconnection) | All commenters on this noteable. (see [Connections](#connections)) |
| <a id="vulnerabilityconfirmedat"></a>`confirmedAt` | [`Time`](#time) | Timestamp of when the vulnerability state was changed to confirmed. |
| <a id="vulnerabilityconfirmedby"></a>`confirmedBy` | [`UserCore`](#usercore) | User that confirmed the vulnerability. |
Loading
Loading
@@ -375,10 +375,11 @@ export default {
:loading="isProcessingAction"
:show-download-patch="canDownloadPatch"
:show-create-merge-request="canCreateMergeRequest"
:show-resolve-with-ai="glAbilities.resolveVulnerabilityWithAi"
:show-explain-with-ai="glAbilities.explainVulnerabilityWithAi"
:resolve-with-ai-ability="glAbilities.resolveVulnerabilityWithAi"
:explain-with-ai-ability="glAbilities.explainVulnerabilityWithAi"
:ai-explanation-available="vulnerability.aiExplanationAvailable"
:ai-resolution-available="vulnerability.aiResolutionAvailable"
:ai-resolution-enabled="vulnerability.aiResolutionEnabled"
@create-merge-request="createMergeRequest"
@download-patch="downloadPatch"
@explain-vulnerability="explainVulnerability"
Loading
Loading
Loading
Loading
@@ -68,12 +68,12 @@ export default {
required: false,
default: false,
},
showExplainWithAi: {
explainWithAiAbility: {
type: Boolean,
required: false,
default: false,
},
showResolveWithAi: {
resolveWithAiAbility: {
type: Boolean,
required: false,
default: false,
Loading
Loading
@@ -88,6 +88,11 @@ export default {
required: false,
default: false,
},
aiResolutionEnabled: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
onlyAiActionsAvailable() {
Loading
Loading
@@ -114,14 +119,14 @@ export default {
availableActions.push(DOWNLOAD_PATCH_ACTION);
}
 
if (this.showExplainWithAi && this.aiExplanationAvailable) {
if (this.explainWithAiAbility && this.aiExplanationAvailable) {
availableActions.push(EXPLAIN_VULNERABILITY_ACTION);
}
 
if (this.showResolveWithAi) {
if (this.resolveWithAiAbility && this.aiResolutionAvailable) {
availableActions.push({
...RESOLVE_VULNERABILITY_ACTION,
...(!this.aiResolutionAvailable && {
...(!this.aiResolutionEnabled && {
disabled: true,
extraAttrs: { disabled: true },
description: RESOLVE_VULNERABILITY_ACTION.disabledStateDescription,
Loading
Loading
Loading
Loading
@@ -139,6 +139,10 @@ class VulnerabilityType < BaseObject
null: true,
description: 'Indicates whether this type of vulnerability can be resolved with AI.'
 
field :ai_resolution_enabled, GraphQL::Types::Boolean,
null: true,
description: 'Indicates whether this specific vulnerability can be resolved with AI.'
markdown_field :description_html, null: true
 
def dismissal_reason
Loading
Loading
@@ -226,6 +230,10 @@ def ai_resolution_available
object.finding&.ai_resolution_available?
end
 
def ai_resolution_enabled
object.finding&.ai_resolution_enabled?
end
private
 
def expose_false_positive?
Loading
Loading
Loading
Loading
@@ -83,6 +83,7 @@ def vulnerability_finding_data(vulnerability)
data[:solution_html] = markdown(vulnerability.present.solution)
data[:ai_explanation_available] = vulnerability.finding.ai_explanation_available?
data[:ai_resolution_available] = vulnerability.finding.ai_resolution_available?
data[:ai_resolution_enabled] = vulnerability.finding.ai_resolution_enabled?
data
end
end
Loading
Loading
Loading
Loading
@@ -550,7 +550,11 @@ def ai_explanation_available?
end
 
def ai_resolution_available?
AI_ALLOWED_REPORT_TYPES.include?(report_type) && HIGH_CONFIDENCE_AI_RESOLUTION_CWES.include?(cwe_value&.upcase)
AI_ALLOWED_REPORT_TYPES.include?(report_type)
end
def ai_resolution_enabled?
ai_resolution_available? && HIGH_CONFIDENCE_AI_RESOLUTION_CWES.include?(cwe_value&.upcase)
end
 
protected
Loading
Loading
Loading
Loading
@@ -350,6 +350,7 @@ describe('Vulnerability Header', () => {
canCreateMergeRequest: actionsEnabled,
canDownloadPatch: actionsEnabled,
aiResolutionAvailable: actionsEnabled,
aiResolutionEnabled: actionsEnabled,
}),
glAbilities: {
resolveVulnerabilityWithAi: actionsEnabled,
Loading
Loading
@@ -363,9 +364,10 @@ describe('Vulnerability Header', () => {
loading: false,
showDownloadPatch: actionsEnabled,
showCreateMergeRequest: actionsEnabled,
showExplainWithAi: actionsEnabled,
showResolveWithAi: actionsEnabled,
explainWithAiAbility: actionsEnabled,
resolveWithAiAbility: actionsEnabled,
aiResolutionAvailable: actionsEnabled,
aiResolutionEnabled: actionsEnabled,
});
});
});
Loading
Loading
Loading
Loading
@@ -10,10 +10,11 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
propsData: {
showDownloadPatch: false,
showCreateMergeRequest: false,
showExplainWithAi: false,
showResolveWithAi: false,
explainWithAiAbility: false,
resolveWithAiAbility: false,
aiResolutionAvailable: true,
aiExplanationAvailable: true,
aiResolutionEnabled: true,
...propsData,
},
});
Loading
Loading
@@ -41,7 +42,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
description: "Create a merge request to apply the scanner's software patch.",
};
const EXPLAIN_WITH_AI_ACTION = {
propToEnable: 'showExplainWithAi',
propToEnable: 'explainWithAiAbility',
name: 'explain-vulnerability',
text: 'Explain with AI',
description:
Loading
Loading
@@ -49,7 +50,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
icon: 'tanuki-ai',
};
const RESOLVE_WITH_AI_ACTION = {
propToEnable: 'showResolveWithAi',
propToEnable: 'resolveWithAiAbility',
name: 'resolve-vulnerability',
text: 'Resolve with AI',
description: 'Use GitLab Duo to generate a merge request with a suggested solution.',
Loading
Loading
@@ -112,8 +113,8 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
createWrapper({
showDownloadPatch: true,
showCreateMergeRequest: true,
showExplainWithAi: true,
showResolveWithAi: true,
explainWithAiAbility: true,
resolveWithAiAbility: true,
aiResolutionAvailable: true,
});
});
Loading
Loading
@@ -152,8 +153,8 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
createWrapper({
showDownloadPatch: nonAiActionsEnabled,
showCreateMergeRequest: nonAiActionsEnabled,
showExplainWithAi: true,
showResolveWithAi: true,
explainWithAiAbility: true,
resolveWithAiAbility: true,
});
});
 
Loading
Loading
@@ -167,18 +168,31 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
},
);
 
it.each([true, false])(
'shows/hides the "Resolve with AI" action when "aiResolutionAvailable is "%s"',
(aiResolutionAvailable) => {
createWrapper({
explainWithAiAbility: true,
resolveWithAiAbility: true,
aiResolutionAvailable,
});
expect(findActionItem(RESOLVE_WITH_AI_ACTION.name).exists()).toBe(aiResolutionAvailable);
},
);
describe.each`
aiResolutionAvailable | expectActionToBeDisabled | expectLinkToDocs
${true} | ${false} | ${false}
${false} | ${true} | ${true}
aiResolutionEnabled | expectActionToBeDisabled | expectLinkToDocs
${true} | ${false} | ${false}
${false} | ${true} | ${true}
`(
'when the ai-resolution is "$aiResolutionAvailable"',
({ aiResolutionAvailable, expectActionToBeDisabled, expectLinkToDocs }) => {
'when the ai-resolution-enabled is "$aiResolutionEnabled"',
({ aiResolutionEnabled, expectActionToBeDisabled, expectLinkToDocs }) => {
beforeEach(() => {
createWrapper({
showExplainWithAi: true,
showResolveWithAi: true,
aiResolutionAvailable,
explainWithAiAbility: true,
resolveWithAiAbility: true,
aiResolutionEnabled,
});
});
 
Loading
Loading
@@ -220,7 +234,7 @@ describe('ee/vulnerabilities/components/vulnerability_actions_dropdown.vue', ()
'shows/hides the "Explain with AI" action when the "aiExplanationAvailable" prop is "%s"',
(aiExplanationAvailable) => {
createWrapper({
showExplainWithAi: true,
explainWithAiAbility: true,
aiExplanationAvailable,
});
 
Loading
Loading
Loading
Loading
@@ -67,6 +67,7 @@
present_on_default_branch
cvss
aiResolutionAvailable
aiResolutionEnabled
]
end
 
Loading
Loading
@@ -309,6 +310,24 @@
 
subject { vulnerabilities.first['aiResolutionAvailable'] }
 
context 'when the vulnerability is of type SAST' do
it { is_expected.to be true }
end
context 'when the vulnerability is not of type SAST' do
before do
vulnerability.finding.update!(report_type: 'dast')
end
it { is_expected.to be false }
end
end
describe 'aiResolutionEnabled' do
let(:query_field) { 'aiResolutionEnabled' }
subject { vulnerabilities.first['aiResolutionEnabled'] }
context 'when the vulnerability is of a supported CWE' do
before do
vulnerability.finding.identifiers << create(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
Loading
Loading
Loading
Loading
@@ -377,7 +377,8 @@
issue_links: kind_of(Array),
merge_request_links: kind_of(Array),
ai_explanation_available: finding.ai_explanation_available?,
ai_resolution_available: finding.ai_resolution_available?
ai_resolution_available: finding.ai_resolution_available?,
ai_resolution_enabled: finding.ai_resolution_enabled?
)
 
expect(subject[:location]['blob_path']).to match(kind_of(String))
Loading
Loading
Loading
Loading
@@ -1701,23 +1701,36 @@
describe '#ai_resolution_available?' do
let(:finding) { build(:vulnerabilities_finding) }
 
it 'returns true when the finding is a supported CWE' do
finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
it 'returns true if the finding is a SAST finding' do
expect(finding.ai_resolution_available?).to be true
end
 
it 'returns false when the finding is an unsupported CWE' do
finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-1')
expect(finding.ai_resolution_available?).to be false
end
it 'returns false if the finding is not a SAST finding' do
finding.report_type = 'dast'
finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: 'CWE-23')
expect(finding.ai_resolution_available?).to be false
end
end
 
describe '#ai_resolution_enabled?' do
using RSpec::Parameterized::TableSyntax
let(:finding) { build(:vulnerabilities_finding) }
where(:finding_report_type, :cwe, :enabled_value) do
'sast' | 'CWE-1' | false
'sast' | 'CWE-23' | true
'dast' | 'CWE-1' | false
'dast' | 'CWE-23' | false
end
with_them do
it 'returns the expected value for enabled' do
finding.report_type = finding_report_type
finding.identifiers << build(:vulnerabilities_identifier, external_type: 'cwe', name: cwe)
expect(finding.ai_resolution_enabled?).to be enabled_value
end
end
end
context 'with loose foreign key on vulnerability_occurrences.project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
let_it_be(:parent) { create(:project) }
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment