Commit 9d7836ba authored by samdbeckham's avatar samdbeckham

Adds source branch support to auto MRs

- Updates merge_request_url to merge_request_path after a backend change
- Adds target_branch to merge request creation request
- Adds sourceBranch to the security reports so we know what to target
parent 082d19bf
......@@ -15,6 +15,7 @@ export default () => {
const datasetOptions = securityTab.dataset;
const {
headBlobPath,
sourceBranch,
sastHeadPath,
sastHelpPath,
dependencyScanningHeadPath,
......@@ -44,6 +45,7 @@ export default () => {
return createElement('security-report-app', {
props: {
headBlobPath,
sourceBranch,
sastHeadPath,
sastHelpPath,
dependencyScanningHeadPath,
......
......@@ -177,7 +177,7 @@ export default {
},
[types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload) {
// We don't cancel the loading state here because we're navigating away from the page
visitUrl(payload.merge_request_url);
visitUrl(payload.merge_request_path);
},
[types.RECEIVE_CREATE_MERGE_REQUEST_ERROR](state) {
state.isCreatingIssue = false;
......
......@@ -242,6 +242,7 @@ export default {
<grouped-security-reports-app
v-if="shouldRenderSecurityReport"
:head-blob-path="mr.headBlobPath"
:source-branch="mr.sourceBranch"
:base-blob-path="mr.baseBlobPath"
:sast-head-path="mr.sast.head_path"
:sast-base-path="mr.sast.base_path"
......
......@@ -64,7 +64,7 @@ export default {
buttons.push(issueButton);
}
if (!this.vulnerability.hasMergeRequest) {
if (!this.vulnerability.hasMergeRequest && this.remediation) {
buttons.push(MRButton);
}
......@@ -119,12 +119,11 @@ export default {
const { data } = this.modal;
const result = {};
for (let key in data) {
// debugger;
Object.keys(data).forEach(key => {
if (data[key].value && data[key].value.length) {
result[key] = data[key];
}
}
});
return result;
},
......@@ -273,7 +272,7 @@ export default {
:author-name="mergeRequestFeedback.author.name"
:author-username="mergeRequestFeedback.author.username"
:action-link-text="`!${mergeRequestFeedback.merge_request_iid}`"
:action-link-url="mergeRequestFeedback.merge_request_url"
:action-link-url="mergeRequestFeedback.merge_request_path"
/>
</li>
</ul>
......@@ -331,6 +330,7 @@ export default {
:disabled="actionButtons[0].isLoading"
:label="actionButtons[0].name"
container-class="btn btn-success btn-inverted"
class="js-action-button"
@click="$emit(actionButtons[0].action)"
/>
</template>
......
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlDropdown,
GlDropdownItem,
Icon,
},
props: {
buttons: {
......@@ -33,16 +34,24 @@ export default {
<template>
<gl-dropdown
v-if="selectedButton"
split
no-caret
right
split
variant="success"
:text="selectedButton.name"
@click="handleClick"
>
<gl-dropdown-item v-for="button in buttons" :key="button.action" @click="setButton(button)">
<strong>{{ button.name }}</strong>
<br />
<span>{{ button.tagline }}</span>
<div class="media">
<div>
<icon v-if="selectedButton === button" class="append-right-5" name="mobile-issue-close" />
</div>
<div class="media-body" :class="{ 'prepend-left-20': selectedButton !== button }">
<strong>{{ button.name }}</strong>
<br />
<span>{{ button.tagline }}</span>
</div>
</div>
</gl-dropdown-item>
</gl-dropdown>
</template>
......@@ -29,6 +29,11 @@ export default {
required: false,
default: null,
},
sourceBranch: {
type: String,
required: false,
default: null,
},
sastHeadPath: {
type: String,
required: false,
......@@ -150,6 +155,7 @@ export default {
created() {
this.setHeadBlobPath(this.headBlobPath);
this.setBaseBlobPath(this.baseBlobPath);
this.setSourceBranch(this.sourceBranch);
this.setVulnerabilityFeedbackPath(this.vulnerabilityFeedbackPath);
this.setVulnerabilityFeedbackHelpPath(this.vulnerabilityFeedbackHelpPath);
......@@ -199,6 +205,7 @@ export default {
'setAppType',
'setHeadBlobPath',
'setBaseBlobPath',
'setSourceBranch',
'setSastHeadPath',
'setSastBasePath',
'setSastContainerHeadPath',
......
......@@ -26,6 +26,11 @@ export default {
type: String,
required: true,
},
sourceBranch: {
type: String,
required: false,
default: null,
},
sastHeadPath: {
type: String,
required: false,
......@@ -141,6 +146,7 @@ export default {
created() {
// update the store with the received props
this.setHeadBlobPath(this.headBlobPath);
this.setSourceBranch(this.sourceBranch);
this.setVulnerabilityFeedbackPath(this.vulnerabilityFeedbackPath);
this.setVulnerabilityFeedbackHelpPath(this.vulnerabilityFeedbackHelpPath);
this.setPipelineId(this.pipelineId);
......@@ -183,6 +189,7 @@ export default {
methods: {
...mapActions([
'setHeadBlobPath',
'setSourceBranch',
'setSastHeadPath',
'setDependencyScanningHeadPath',
'setSastContainerHeadPath',
......@@ -199,6 +206,7 @@ export default {
'dismissIssue',
'revertDismissIssue',
'createNewIssue',
'createMergeRequest',
]),
summaryTextBuilder(reportType, issuesCount = 0) {
if (issuesCount === 0) {
......@@ -282,6 +290,7 @@ export default {
:can-create-issue-permission="canCreateIssuePermission"
:can-create-feedback-permission="canCreateFeedbackPermission"
@createNewIssue="createNewIssue"
@createMergeRequest="createMergeRequest"
@dismissIssue="dismissIssue"
@revertDismissIssue="revertDismissIssue"
/>
......
......@@ -8,6 +8,8 @@ export const setHeadBlobPath = ({ commit }, blobPath) => commit(types.SET_HEAD_B
export const setBaseBlobPath = ({ commit }, blobPath) => commit(types.SET_BASE_BLOB_PATH, blobPath);
export const setSourceBranch = ({ commit }, branch) => commit(types.SET_SOURCE_BRANCH, branch);
export const setVulnerabilityFeedbackPath = ({ commit }, path) =>
commit(types.SET_VULNERABILITY_FEEDBACK_PATH, path);
......@@ -335,6 +337,8 @@ export const createMergeRequest = ({ state, dispatch }) => {
const { vulnerability } = state.modal;
const { category, project_fingerprint } = vulnerability;
vulnerability.target_branch = state.sourceBranch;
dispatch('requestCreateMergeRequest');
axios
......
export const SET_HEAD_BLOB_PATH = 'SET_HEAD_BLOB_PATH';
export const SET_BASE_BLOB_PATH = 'SET_BASE_BLOB_PATH';
export const SET_SOURCE_BRANCH = 'SET_SOURCE_BRANCH';
export const SET_VULNERABILITY_FEEDBACK_PATH = 'SET_VULNERABILITY_FEEDBACK_PATH';
export const SET_VULNERABILITY_FEEDBACK_HELP_PATH = 'SET_VULNERABILITY_FEEDBACK_HELP_PATH';
export const SET_PIPELINE_ID = 'SET_PIPELINE_ID';
......
......@@ -20,6 +20,10 @@ export default {
Vue.set(state.blobPath, 'base', path);
},
[types.SET_SOURCE_BRANCH](state, branch) {
state.sourceBranch = branch;
},
[types.SET_VULNERABILITY_FEEDBACK_PATH](state, path) {
state.vulnerabilityFeedbackPath = path;
},
......@@ -419,7 +423,7 @@ export default {
},
[types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload) {
// We don't cancel the loading state here because we're navigating away from the page
visitUrl(payload.merge_request_url);
visitUrl(payload.merge_request_path);
},
[types.RECEIVE_CREATE_MERGE_REQUEST_ERROR](state, error) {
state.isCreatingMergeRequest = false;
......
......@@ -12,6 +12,7 @@ export default () => ({
base: null,
},
sourceBranch: null,
vulnerabilityFeedbackPath: null,
vulnerabilityFeedbackHelpPath: null,
pipelineId: null,
......
......@@ -16,6 +16,7 @@
dast_head_path: dast_endpoint,
sast_container_head_path: sast_container_endpoint,
pipeline_id: pipeline.id,
source_branch: pipeline.ref,
vulnerability_feedback_path: project_vulnerability_feedback_index_path(project),
vulnerability_feedback_help_path: help_page_path("user/project/merge_requests/index", anchor: "interacting-with-security-reports-ultimate"),
sast_help_path: help_page_path('user/project/merge_requests/sast'),
......
......@@ -463,7 +463,7 @@ describe('issue creation', () => {
describe('merge request creation', () => {
describe('createMergeRequest', () => {
const vulnerability = mockDataVulnerabilities[0];
const data = { merge_request_url: 'fakepath.html' };
const data = { merge_request_path: 'fakepath.html' };
let mock;
beforeEach(() => {
......
......@@ -413,11 +413,11 @@ describe('vulnerabilities module mutations', () => {
describe('RECEIVE_CREATE_MERGE_REQUEST_SUCCESS', () => {
it('should fire the visitUrl function on the merge request URL', () => {
const state = createState();
const payload = { merge_request_url: 'fakepath.html' };
const payload = { merge_request_path: 'fakepath.html' };
const visitUrl = spyOnDependency(mutations, 'visitUrl');
mutations[types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload);
expect(visitUrl).toHaveBeenCalledWith(payload.merge_request_url);
expect(visitUrl).toHaveBeenCalledWith(payload.merge_request_path);
});
});
......
......@@ -97,6 +97,10 @@ describe('Security Reports modal', () => {
expect(vm.$el.querySelector('.js-dismiss-btn')).toBe(null);
});
it('renders create issue button', () => {
expect(vm.$el.querySelector('.js-action-button')).not.toBe(null);
});
it('renders the footer', () => {
expect(vm.$el.classList.contains('modal-hide-footer')).toEqual(false);
});
......@@ -104,7 +108,7 @@ describe('Security Reports modal', () => {
it('emits createIssue when create issue button is clicked', () => {
spyOn(vm, '$emit');
const button = vm.$el.querySelector('.js-split-button').querySelector('.btn-success');
const button = vm.$el.querySelector('.js-action-button');
button.click();
expect(vm.$emit).toHaveBeenCalledWith('createNewIssue');
......
......@@ -517,11 +517,11 @@ describe('security reports mutations', () => {
describe('RECEIVE_CREATE_MERGE_REQUEST_SUCCESS', () => {
it('should fire the visitUrl function on the merge request URL', () => {
const payload = { merge_request_url: 'fakepath.html' };
const payload = { merge_request_path: 'fakepath.html' };
const visitUrl = spyOnDependency(mutations, 'visitUrl');
mutations[types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](stateCopy, payload);
expect(visitUrl).toHaveBeenCalledWith(payload.merge_request_url);
expect(visitUrl).toHaveBeenCalledWith(payload.merge_request_path);
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment