Commit fc53ce8e authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 8e22ef10
...@@ -35,10 +35,10 @@ export default { ...@@ -35,10 +35,10 @@ export default {
title() { title() {
const timeago = getTimeago(); const timeago = getTimeago();
const { timeDifference, standardDateFormat } = this; const { timeDifference, standardDateFormat } = this;
const formatedDate = standardDateFormat; const formattedDate = standardDateFormat;
if (timeDifference >= -1 && timeDifference < 7) { if (timeDifference >= -1 && timeDifference < 7) {
return `${timeago.format(this.issueDueDate)} (${formatedDate})`; return `${timeago.format(this.issueDueDate)} (${formattedDate})`;
} }
return timeago.format(this.issueDueDate); return timeago.format(this.issueDueDate);
......
...@@ -159,7 +159,7 @@ export default { ...@@ -159,7 +159,7 @@ export default {
<div role="rowheader" class="table-mobile-header">{{ __('Created') }}</div> <div role="rowheader" class="table-mobile-header">{{ __('Created') }}</div>
<div class="table-mobile-content text-secondary key-created-at"> <div class="table-mobile-content text-secondary key-created-at">
<span v-tooltip :title="tooltipTitle(deployKey.created_at)"> <span v-tooltip :title="tooltipTitle(deployKey.created_at)">
<icon name="calendar" /> <span>{{ timeFormated(deployKey.created_at) }}</span> <icon name="calendar" /> <span>{{ timeFormatted(deployKey.created_at) }}</span>
</span> </span>
</div> </div>
</div> </div>
......
...@@ -177,6 +177,7 @@ export default { ...@@ -177,6 +177,7 @@ export default {
projectPath: this.projectPath, projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint, dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover, showSuggestPopover: this.showSuggestPopover,
useSingleDiffStyle: this.glFeatures.singleMrDiffView,
}); });
if (this.shouldShow) { if (this.shouldShow) {
......
...@@ -46,6 +46,7 @@ export const setBaseConfig = ({ commit }, options) => { ...@@ -46,6 +46,7 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
} = options; } = options;
commit(types.SET_BASE_CONFIG, { commit(types.SET_BASE_CONFIG, {
endpoint, endpoint,
...@@ -54,11 +55,15 @@ export const setBaseConfig = ({ commit }, options) => { ...@@ -54,11 +55,15 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
}); });
}; };
export const fetchDiffFiles = ({ state, commit }) => { export const fetchDiffFiles = ({ state, commit }) => {
const worker = new TreeWorker(); const worker = new TreeWorker();
const urlParams = {
w: state.showWhitespace ? '0' : '1',
};
commit(types.SET_LOADING, true); commit(types.SET_LOADING, true);
...@@ -69,9 +74,10 @@ export const fetchDiffFiles = ({ state, commit }) => { ...@@ -69,9 +74,10 @@ export const fetchDiffFiles = ({ state, commit }) => {
}); });
return axios return axios
.get(mergeUrlParams({ w: state.showWhitespace ? '0' : '1' }, state.endpoint)) .get(mergeUrlParams(urlParams, state.endpoint))
.then(res => { .then(res => {
commit(types.SET_LOADING, false); commit(types.SET_LOADING, false);
commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []); commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
commit(types.SET_DIFF_DATA, res.data); commit(types.SET_DIFF_DATA, res.data);
......
...@@ -31,4 +31,5 @@ export default () => ({ ...@@ -31,4 +31,5 @@ export default () => ({
fileFinderVisible: false, fileFinderVisible: false,
dismissEndpoint: '', dismissEndpoint: '',
showSuggestPopover: true, showSuggestPopover: true,
useSingleDiffStyle: false,
}); });
...@@ -19,6 +19,7 @@ export default { ...@@ -19,6 +19,7 @@ export default {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
} = options; } = options;
Object.assign(state, { Object.assign(state, {
endpoint, endpoint,
...@@ -27,6 +28,7 @@ export default { ...@@ -27,6 +28,7 @@ export default {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
}); });
}, },
......
...@@ -56,7 +56,7 @@ export default { ...@@ -56,7 +56,7 @@ export default {
__('Reported %{timeAgo} by %{reportedBy}'), __('Reported %{timeAgo} by %{reportedBy}'),
{ {
reportedBy: `<strong>${this.error.culprit}</strong>`, reportedBy: `<strong>${this.error.culprit}</strong>`,
timeAgo: this.timeFormated(this.stacktraceData.date_received), timeAgo: this.timeFormatted(this.stacktraceData.date_received),
}, },
false, false,
); );
...@@ -107,7 +107,7 @@ export default { ...@@ -107,7 +107,7 @@ export default {
this.$refs.sentryIssueForm.submit(); this.$refs.sentryIssueForm.submit();
}, },
formatDate(date) { formatDate(date) {
return `${this.timeFormated(date)} (${dateFormat(date, 'UTC:yyyy-mm-dd h:MM:ssTT Z')})`; return `${this.timeFormatted(date)} (${dateFormat(date, 'UTC:yyyy-mm-dd h:MM:ssTT Z')})`;
}, },
}, },
}; };
......
...@@ -22,7 +22,7 @@ export default { ...@@ -22,7 +22,7 @@ export default {
mixins: [timeAgoMixin], mixins: [timeAgoMixin],
data() { data() {
return { return {
lastCommitFormatedAge: null, lastCommitFormattedAge: null,
}; };
}, },
computed: { computed: {
...@@ -62,7 +62,7 @@ export default { ...@@ -62,7 +62,7 @@ export default {
}, },
commitAgeUpdate() { commitAgeUpdate() {
if (this.lastCommit) { if (this.lastCommit) {
this.lastCommitFormatedAge = this.timeFormated(this.lastCommit.committed_date); this.lastCommitFormattedAge = this.timeFormatted(this.lastCommit.committed_date);
} }
}, },
getCommitPath(shortSha) { getCommitPath(shortSha) {
...@@ -118,7 +118,7 @@ export default { ...@@ -118,7 +118,7 @@ export default {
:title="tooltipTitle(lastCommit.committed_date)" :title="tooltipTitle(lastCommit.committed_date)"
data-placement="top" data-placement="top"
data-container="body" data-container="body"
>{{ lastCommitFormatedAge }}</time >{{ lastCommitFormattedAge }}</time
> >
</div> </div>
<ide-status-list class="ml-auto" /> <ide-status-list class="ml-auto" />
......
...@@ -91,7 +91,7 @@ export default { ...@@ -91,7 +91,7 @@ export default {
/> />
<gl-tooltip :target="() => $refs.state" placement="bottom"> <gl-tooltip :target="() => $refs.state" placement="bottom">
<span class="d-block"> <span class="d-block">
<span class="bold"> {{ stateTitle }} </span> {{ timeFormated(closedOrCreatedDate) }} <span class="bold"> {{ stateTitle }} </span> {{ timeFormatted(closedOrCreatedDate) }}
</span> </span>
<span class="text-tertiary">{{ tooltipTitle(closedOrCreatedDate) }}</span> <span class="text-tertiary">{{ tooltipTitle(closedOrCreatedDate) }}</span>
</gl-tooltip> </gl-tooltip>
......
...@@ -168,13 +168,13 @@ export default { ...@@ -168,13 +168,13 @@ export default {
/> />
<detail-row <detail-row
v-if="job.finished_at" v-if="job.finished_at"
:value="timeFormated(job.finished_at)" :value="timeFormatted(job.finished_at)"
class="js-job-finished" class="js-job-finished"
title="Finished" title="Finished"
/> />
<detail-row <detail-row
v-if="job.erased_at" v-if="job.erased_at"
:value="timeFormated(job.erased_at)" :value="timeFormatted(job.erased_at)"
class="js-job-erased" class="js-job-erased"
title="Erased" title="Erased"
/> />
......
...@@ -114,7 +114,7 @@ export const logLinesParser = (lines = [], accumulator = []) => ...@@ -114,7 +114,7 @@ export const logLinesParser = (lines = [], accumulator = []) =>
acc.push(parseHeaderLine(line, lineNumber)); acc.push(parseHeaderLine(line, lineNumber));
} else if (isCollapsibleSection(acc, last, line)) { } else if (isCollapsibleSection(acc, last, line)) {
// if the object belongs to a nested section, we append it to the new `lines` array of the // if the object belongs to a nested section, we append it to the new `lines` array of the
// previously formated header // previously formatted header
last.lines.push(parseLine(line, lineNumber)); last.lines.push(parseLine(line, lineNumber));
} else if (line.section_duration) { } else if (line.section_duration) {
// if the line has section_duration, we look for the correct header to add it // if the line has section_duration, we look for the correct header to add it
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import $ from 'jquery'; import $ from 'jquery';
import axios from './axios_utils'; import axios from './axios_utils';
import { getLocationHash } from './url_utility'; import { getLocationHash } from './url_utility';
import { convertToCamelCase } from './text_utility'; import { convertToCamelCase, convertToSnakeCase } from './text_utility';
import { isObject } from './type_utility'; import { isObject } from './type_utility';
import breakpointInstance from '../../breakpoints'; import breakpointInstance from '../../breakpoints';
...@@ -697,6 +697,22 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => { ...@@ -697,6 +697,22 @@ export const convertObjectPropsToCamelCase = (obj = {}, options = {}) => {
}, initial); }, initial);
}; };
/**
* Converts all the object keys to snake case
*
* @param {Object} obj Object to transform
* @returns {Object}
*/
// Follow up to add additional options param:
// https://gitlab.com/gitlab-org/gitlab/issues/39173
export const convertObjectPropsToSnakeCase = (obj = {}) =>
obj
? Object.entries(obj).reduce(
(acc, [key, value]) => ({ ...acc, [convertToSnakeCase(key)]: value }),
{},
)
: {};
export const imagePath = imgUrl => export const imagePath = imgUrl =>
`${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`; `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`;
......
...@@ -447,7 +447,7 @@ export const parsePikadayDate = dateString => { ...@@ -447,7 +447,7 @@ export const parsePikadayDate = dateString => {
/** /**
* Used `onSelect` method in pickaday * Used `onSelect` method in pickaday
* @param {Date} date UTC format * @param {Date} date UTC format
* @return {String} Date formated in yyyy-mm-dd * @return {String} Date formatted in yyyy-mm-dd
*/ */
export const pikadayToString = date => { export const pikadayToString = date => {
const day = pad(date.getDate()); const day = pad(date.getDate());
...@@ -513,8 +513,8 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => { ...@@ -513,8 +513,8 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => {
if (fullNameFormat && isNonZero) { if (fullNameFormat && isNonZero) {
// Remove traling 's' if unit value is singular // Remove traling 's' if unit value is singular
const formatedUnitName = unitValue > 1 ? unitName : unitName.replace(/s$/, ''); const formattedUnitName = unitValue > 1 ? unitName : unitName.replace(/s$/, '');
return `${memo} ${unitValue} ${formatedUnitName}`; return `${memo} ${unitValue} ${formattedUnitName}`;
} }
return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo; return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
......
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
return this.mergeRequest.headPipeline && this.mergeRequest.headPipeline.detailedStatus; return this.mergeRequest.headPipeline && this.mergeRequest.headPipeline.detailedStatus;
}, },
formattedTime() { formattedTime() {
return this.timeFormated(this.mergeRequest.createdAt); return this.timeFormatted(this.mergeRequest.createdAt);
}, },
statusBoxClass() { statusBoxClass() {
switch (this.mergeRequest.state) { switch (this.mergeRequest.state) {
......
...@@ -31,7 +31,7 @@ export default { ...@@ -31,7 +31,7 @@ export default {
hasFinishedTime() { hasFinishedTime() {
return this.finishedTime !== ''; return this.finishedTime !== '';
}, },
durationFormated() { durationFormatted() {
const date = new Date(this.duration * 1000); const date = new Date(this.duration * 1000);
let hh = date.getUTCHours(); let hh = date.getUTCHours();
...@@ -59,7 +59,7 @@ export default { ...@@ -59,7 +59,7 @@ export default {
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Duration') }}</div> <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Duration') }}</div>
<div class="table-mobile-content"> <div class="table-mobile-content">
<p v-if="hasDuration" class="duration"> <p v-if="hasDuration" class="duration">
<span v-html="iconTimerSvg"> </span> {{ durationFormated }} <span v-html="iconTimerSvg"> </span> {{ durationFormatted }}
</p> </p>
<p v-if="hasFinishedTime" class="finished-at d-none d-sm-none d-md-block"> <p v-if="hasFinishedTime" class="finished-at d-none d-sm-none d-md-block">
...@@ -71,7 +71,7 @@ export default { ...@@ -71,7 +71,7 @@ export default {
data-placement="top" data-placement="top"
data-container="body" data-container="body"
> >
{{ timeFormated(finishedTime) }} {{ timeFormatted(finishedTime) }}
</time> </time>
</p> </p>
</div> </div>
......
...@@ -247,7 +247,7 @@ export default { ...@@ -247,7 +247,7 @@ export default {
<td> <td>
<span v-gl-tooltip.bottom :title="tooltipTitle(item.createdAt)">{{ <span v-gl-tooltip.bottom :title="tooltipTitle(item.createdAt)">{{
timeFormated(item.createdAt) timeFormatted(item.createdAt)
}}</span> }}</span>
</td> </td>
......
...@@ -48,7 +48,7 @@ export default { ...@@ -48,7 +48,7 @@ export default {
}, },
releasedTimeAgo() { releasedTimeAgo() {
return sprintf(__('released %{time}'), { return sprintf(__('released %{time}'), {
time: this.timeFormated(this.release.released_at), time: this.timeFormatted(this.release.released_at),
}); });
}, },
userImageAltDescription() { userImageAltDescription() {
......
...@@ -50,7 +50,7 @@ export default { ...@@ -50,7 +50,7 @@ export default {
}, },
computed: { computed: {
releasedAtTimeAgo() { releasedAtTimeAgo() {
return this.timeFormated(this.releasedAt); return this.timeFormatted(this.releasedAt);
}, },
userImageAltDescription() { userImageAltDescription() {
return this.author && this.author.username return this.author && this.author.username
......
...@@ -41,7 +41,7 @@ export default { ...@@ -41,7 +41,7 @@ export default {
}, },
computed: { computed: {
deployTimeago() { deployTimeago() {
return this.timeFormated(this.deployment.deployed_at); return this.timeFormatted(this.deployment.deployed_at);
}, },
deployedText() { deployedText() {
return this.$options.deployedTextMap[this.computedDeploymentStatus]; return this.$options.deployedTextMap[this.computedDeploymentStatus];
......
...@@ -54,7 +54,7 @@ export default { ...@@ -54,7 +54,7 @@ export default {
return timeFor( return timeFor(
this.milestoneDue, this.milestoneDue,
sprintf(__('Expired %{expiredOn}'), { sprintf(__('Expired %{expiredOn}'), {
expiredOn: this.timeFormated(this.milestoneDue), expiredOn: this.timeFormatted(this.milestoneDue),
}), }),
); );
} }
...@@ -62,7 +62,7 @@ export default { ...@@ -62,7 +62,7 @@ export default {
return sprintf( return sprintf(
this.isMilestoneStarted ? __('Started %{startsIn}') : __('Starts %{startsIn}'), this.isMilestoneStarted ? __('Started %{startsIn}') : __('Starts %{startsIn}'),
{ {
startsIn: this.timeFormated(this.milestoneStart), startsIn: this.timeFormatted(this.milestoneStart),
}, },
); );
} }
......
...@@ -64,7 +64,7 @@ export default { ...@@ -64,7 +64,7 @@ export default {
tooltipText(dateType = 'min') { tooltipText(dateType = 'min') {
const defaultText = dateType === 'min' ? __('Start date') : __('Due date'); const defaultText = dateType === 'min' ? __('Start date') : __('Due date');
const date = this[`${dateType}Date`]; const date = this[`${dateType}Date`];
const timeAgo = dateType === 'min' ? this.timeFormated(date) : timeFor(date); const timeAgo = dateType === 'min' ? this.timeFormatted(date) : timeFor(date);
const dateText = date ? [this.dateText(dateType), `(${timeAgo})`].join(' ') : ''; const dateText = date ? [this.dateText(dateType), `(${timeAgo})`].join(' ') : '';
if (date) { if (date) {
......
...@@ -35,7 +35,7 @@ export default { ...@@ -35,7 +35,7 @@ export default {
v-gl-tooltip.viewport="{ placement: tooltipPlacement }" v-gl-tooltip.viewport="{ placement: tooltipPlacement }"
:class="cssClass" :class="cssClass"
:title="tooltipTitle(time)" :title="tooltipTitle(time)"
v-text="timeFormated(time)" v-text="timeFormatted(time)"
> >
</time> </time>
</template> </template>
...@@ -159,7 +159,7 @@ const mixins = { ...@@ -159,7 +159,7 @@ const mixins = {
return this.displayReference.split(this.pathIdSeparator).pop(); return this.displayReference.split(this.pathIdSeparator).pop();
}, },
createdAtInWords() { createdAtInWords() {
return this.createdAt ? this.timeFormated(this.createdAt) : ''; return this.createdAt ? this.timeFormatted(this.createdAt) : '';
}, },
createdAtTimestamp() { createdAtTimestamp() {
return this.createdAt ? formatDate(new Date(this.createdAt)) : ''; return this.createdAt ? formatDate(new Date(this.createdAt)) : '';
...@@ -168,10 +168,10 @@ const mixins = { ...@@ -168,10 +168,10 @@ const mixins = {
return this.mergedAt ? formatDate(new Date(this.mergedAt)) : ''; return this.mergedAt ? formatDate(new Date(this.mergedAt)) : '';
}, },
mergedAtInWords() { mergedAtInWords() {
return this.mergedAt ? this.timeFormated(this.mergedAt) : ''; return this.mergedAt ? this.timeFormatted(this.mergedAt) : '';
}, },
closedAtInWords() { closedAtInWords() {
return this.closedAt ? this.timeFormated(this.closedAt) : ''; return this.closedAt ? this.timeFormatted(this.closedAt) : '';
}, },
closedAtTimestamp() { closedAtTimestamp() {
return this.closedAt ? formatDate(new Date(this.closedAt)) : ''; return this.closedAt ? formatDate(new Date(this.closedAt)) : '';
......
...@@ -5,7 +5,7 @@ import { formatDate, getTimeago } from '../../lib/utils/datetime_utility'; ...@@ -5,7 +5,7 @@ import { formatDate, getTimeago } from '../../lib/utils/datetime_utility';
*/ */
export default { export default {
methods: { methods: {
timeFormated(time) { timeFormatted(time) {
const timeago = getTimeago(); const timeago = getTimeago();
return timeago.format(time); return timeago.format(time);
......
...@@ -20,6 +20,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -20,6 +20,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :check_user_can_push_to_source_branch!, only: [:rebase] before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do before_action only: [:show] do
push_frontend_feature_flag(:diffs_batch_load, @project) push_frontend_feature_flag(:diffs_batch_load, @project)
push_frontend_feature_flag(:single_mr_diff_view, @project)
end end
before_action do before_action do
......
---
title: Show merge immediately dialog even if the MR's pipeline hasn't finished
merge_request: 21556
author:
type: changed
...@@ -219,6 +219,94 @@ build_latest_vulnerabilities: ...@@ -219,6 +219,94 @@ build_latest_vulnerabilities:
The above template will work for a GitLab Docker registry running on a local installation, however, if you're using a non-GitLab Docker registry, you'll need to change the `$CI_REGISTRY` value and the `docker login` credentials to match the details of your local registry. The above template will work for a GitLab Docker registry running on a local installation, however, if you're using a non-GitLab Docker registry, you'll need to change the `$CI_REGISTRY` value and the `docker login` credentials to match the details of your local registry.
## Reports JSON format
CAUTION: **Caution:**
The JSON report artifacts are not a public API of Container Scanning and their format may change in the future.
The Container Scanning tool emits a JSON report file. Here is an example of the report structure with all important parts of
it highlighted:
```json-doc
{
"version": "2.3",
"vulnerabilities": [
{
"category": "container_scanning",
"message": "CVE-2019-3462 in apt",
"description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.",
"cve": "debian:9:apt:CVE-2019-3462",
"severity": "High",
"confidence": "Unknown",
"solution": "Upgrade apt from 1.4.8 to 1.4.9",
"scanner": {
"id": "klar",
"name": "klar"
},
"location": {
"dependency": {
"package": {
"name": "apt"
},
"version": "1.4.8"
},
"operating_system": "debian:9",
"image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e"
},
"identifiers": [
{
"type": "cve",
"name": "CVE-2019-3462",
"value": "CVE-2019-3462",
"url": "https://security-tracker.debian.org/tracker/CVE-2019-3462"
}
],
"links": [
{
"url": "https://security-tracker.debian.org/tracker/CVE-2019-3462"
}
]
}
],
"remediations": [
]
}
```
Here is the description of the report file structure nodes and their meaning. All fields are mandatory to be present in
the report JSON unless stated otherwise. Presence of optional fields depends on the underlying analyzers being used.
| Report JSON node | Description |
|------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `version` | Report syntax version used to generate this JSON. |
| `vulnerabilities` | Array of vulnerability objects. |
| `vulnerabilities[].category` | Where this vulnerability belongs (SAST, Container Scanning etc.). For Container Scanning, it will always be `container_scanning`. |
| `vulnerabilities[].message` | A short text that describes the vulnerability, it may include occurrence's specific information. Optional. |
| `vulnerabilities[].description` | A long text that describes the vulnerability. Optional. |
| `vulnerabilities[].cve` | A fingerprint string value that represents a concrete occurrence of the vulnerability. It's used to determine whether two vulnerability occurrences are same or different. May not be 100% accurate. **This is NOT a [CVE](https://cve.mitre.org/)**. |
| `vulnerabilities[].severity` | How much the vulnerability impacts the software. Possible values: `Undefined` (an analyzer has not provided this info), `Info`, `Unknown`, `Low`, `Medium`, `High`, `Critical`. **Note:** Our current container scanning tool based on [klar](https://github.com/optiopay/klar) only provides the following levels: `Unknown`, `Low`, `Medium`, `High`, `Critical`. |
| `vulnerabilities[].confidence` | How reliable the vulnerability's assessment is. Possible values: `Undefined` (an analyzer has not provided this info), `Ignore`, `Unknown`, `Experimental`, `Low`, `Medium`, `High`, `Confirmed`. **Note:** Our current container scanning tool based on [klar](https://github.com/optiopay/klar) does not provide a confidence level, so this value is currently hardcoded to `Unknown`. |
| `vulnerabilities[].solution` | Explanation of how to fix the vulnerability. Optional. |
| `vulnerabilities[].scanner` | A node that describes the analyzer used to find this vulnerability. |
| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
| `vulnerabilities[].location` | A node that tells where the vulnerability is located. |
| `vulnerabilities[].location.dependency` | A node that describes the dependency of a project where the vulnerability is located. |
| `vulnerabilities[].location.dependency.package` | A node that provides the information on the package where the vulnerability is located. |
| `vulnerabilities[].location.dependency.package.name` | Name of the package where the vulnerability is located. |
| `vulnerabilities[].location.dependency.version` | Version of the vulnerable package. Optional. |
| `vulnerabilities[].location.operating_system` | The operating system that contains the vulnerable package. |
| `vulnerabilities[].location.image` | The Docker image that was analyzed. Optional. |
| `vulnerabilities[].identifiers` | An ordered array of references that identify a vulnerability on internal or external DBs. |
| `vulnerabilities[].identifiers[].type` | Type of the identifier. Possible values: common identifier types (among `cve`, `cwe`, `osvdb`, and `usn`). |
| `vulnerabilities[].identifiers[].name` | Name of the identifier for display purpose. |
| `vulnerabilities[].identifiers[].value` | Value of the identifier for matching purpose. |
| `vulnerabilities[].identifiers[].url` | URL to identifier's documentation. Optional. |
| `vulnerabilities[].links` | An array of references to external documentation pieces or articles that describe the vulnerability further. Optional. |
| `vulnerabilities[].links[].name` | Name of the vulnerability details link. Optional. |
| `vulnerabilities[].links[].url` | URL of the vulnerability details document. Optional. |
| `remediations` | Not supported yet. |
## Troubleshooting ## Troubleshooting
### docker: Error response from daemon: failed to copy xattrs ### docker: Error response from daemon: failed to copy xattrs
......
...@@ -5202,6 +5202,9 @@ msgstr "" ...@@ -5202,6 +5202,9 @@ msgstr ""
msgid "CustomCycleAnalytics|Add stage" msgid "CustomCycleAnalytics|Add stage"
msgstr "" msgstr ""
msgid "CustomCycleAnalytics|Editing stage"
msgstr ""
msgid "CustomCycleAnalytics|Enter a name for the stage" msgid "CustomCycleAnalytics|Enter a name for the stage"
msgstr "" msgstr ""
...@@ -5235,6 +5238,9 @@ msgstr "" ...@@ -5235,6 +5238,9 @@ msgstr ""
msgid "CustomCycleAnalytics|Stop event label" msgid "CustomCycleAnalytics|Stop event label"
msgstr "" msgstr ""
msgid "CustomCycleAnalytics|Update stage"
msgstr ""
msgid "Customize colors" msgid "Customize colors"
msgstr "" msgstr ""
......
...@@ -45,9 +45,9 @@ describe('Environment item', () => { ...@@ -45,9 +45,9 @@ describe('Environment item', () => {
}); });
it('should render last deployment date', () => { it('should render last deployment date', () => {
const formatedDate = format(environment.last_deployment.deployed_at); const formattedDate = format(environment.last_deployment.deployed_at);
expect(wrapper.find('.environment-created-date-timeago').text()).toContain(formatedDate); expect(wrapper.find('.environment-created-date-timeago').text()).toContain(formattedDate);
}); });
describe('With user information', () => { describe('With user information', () => {
......
...@@ -8,7 +8,7 @@ describe('Erased block', () => { ...@@ -8,7 +8,7 @@ describe('Erased block', () => {
const erasedAt = '2016-11-07T11:11:16.525Z'; const erasedAt = '2016-11-07T11:11:16.525Z';
const timeago = getTimeago(); const timeago = getTimeago();
const formatedDate = timeago.format(erasedAt); const formattedDate = timeago.format(erasedAt);
const createComponent = props => { const createComponent = props => {
wrapper = mount(ErasedBlock, { wrapper = mount(ErasedBlock, {
...@@ -41,7 +41,7 @@ describe('Erased block', () => { ...@@ -41,7 +41,7 @@ describe('Erased block', () => {
}); });
it('renders erasedAt', () => { it('renders erasedAt', () => {
expect(wrapper.text().trim()).toContain(formatedDate); expect(wrapper.text().trim()).toContain(formattedDate);
}); });
}); });
...@@ -57,7 +57,7 @@ describe('Erased block', () => { ...@@ -57,7 +57,7 @@ describe('Erased block', () => {
}); });
it('renders erasedAt', () => { it('renders erasedAt', () => {
expect(wrapper.text().trim()).toContain(formatedDate); expect(wrapper.text().trim()).toContain(formattedDate);
}); });
}); });
}); });
...@@ -68,7 +68,7 @@ describe('table registry', () => { ...@@ -68,7 +68,7 @@ describe('table registry', () => {
expect(tds.at(2).html()).toContain(repoPropsData.list[0].shortRevision); expect(tds.at(2).html()).toContain(repoPropsData.list[0].shortRevision);
expect(tds.at(3).html()).toContain(repoPropsData.list[0].layers); expect(tds.at(3).html()).toContain(repoPropsData.list[0].layers);
expect(tds.at(3).html()).toContain(repoPropsData.list[0].size); expect(tds.at(3).html()).toContain(repoPropsData.list[0].size);
expect(tds.at(4).html()).toContain(wrapper.vm.timeFormated(repoPropsData.list[0].createdAt)); expect(tds.at(4).html()).toContain(wrapper.vm.timeFormatted(repoPropsData.list[0].createdAt));
}); });
it('should have a label called Image ID', () => { it('should have a label called Image ID', () => {
......
...@@ -8,8 +8,8 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; ...@@ -8,8 +8,8 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
jest.mock('~/vue_shared/mixins/timeago', () => ({ jest.mock('~/vue_shared/mixins/timeago', () => ({
methods: { methods: {
timeFormated() { timeFormatted() {
return '7 fortnightes ago'; return '7 fortnights ago';
}, },
tooltipTitle() { tooltipTitle() {
return 'February 30, 2401'; return 'February 30, 2401';
...@@ -82,7 +82,7 @@ describe('Release block footer', () => { ...@@ -82,7 +82,7 @@ describe('Release block footer', () => {
it('renders the author and creation time info', () => { it('renders the author and creation time info', () => {
expect(trimText(authorDateInfoSection().text())).toBe( expect(trimText(authorDateInfoSection().text())).toBe(
`Created 7 fortnightes ago by ${releaseClone.author.username}`, `Created 7 fortnights ago by ${releaseClone.author.username}`,
); );
}); });
...@@ -139,7 +139,7 @@ describe('Release block footer', () => { ...@@ -139,7 +139,7 @@ describe('Release block footer', () => {
beforeEach(() => factory({ author: undefined })); beforeEach(() => factory({ author: undefined }));
it('renders the release date without the author name', () => { it('renders the release date without the author name', () => {
expect(trimText(authorDateInfoSection().text())).toBe('Created 7 fortnightes ago'); expect(trimText(authorDateInfoSection().text())).toBe('Created 7 fortnights ago');
}); });
}); });
......
...@@ -68,7 +68,7 @@ describe('Release block', () => { ...@@ -68,7 +68,7 @@ describe('Release block', () => {
}); });
it('renders release date', () => { it('renders release date', () => {
expect(wrapper.text()).toContain(timeagoMixin.methods.timeFormated(release.released_at)); expect(wrapper.text()).toContain(timeagoMixin.methods.timeFormatted(release.released_at));
}); });
it('renders number of assets provided', () => { it('renders number of assets provided', () => {
......
...@@ -90,11 +90,11 @@ describe('RelatedIssuableItem', () => { ...@@ -90,11 +90,11 @@ describe('RelatedIssuableItem', () => {
it('renders state title', () => { it('renders state title', () => {
const stateTitle = tokenState.attributes('title'); const stateTitle = tokenState.attributes('title');
const formatedCreateDate = formatDate(props.createdAt); const formattedCreateDate = formatDate(props.createdAt);
expect(stateTitle).toContain('<span class="bold">Opened</span>'); expect(stateTitle).toContain('<span class="bold">Opened</span>');
expect(stateTitle).toContain(`<span class="text-tertiary">${formatedCreateDate}</span>`); expect(stateTitle).toContain(`<span class="text-tertiary">${formattedCreateDate}</span>`);
}); });
it('renders aria label', () => { it('renders aria label', () => {
......
...@@ -41,6 +41,7 @@ describe('diffs/components/app', () => { ...@@ -41,6 +41,7 @@ describe('diffs/components/app', () => {
changesEmptyStateIllustration: '', changesEmptyStateIllustration: '',
dismissEndpoint: '', dismissEndpoint: '',
showSuggestPopover: true, showSuggestPopover: true,
useSingleDiffStyle: false,
...props, ...props,
}, },
store, store,
......
...@@ -75,6 +75,7 @@ describe('DiffsStoreActions', () => { ...@@ -75,6 +75,7 @@ describe('DiffsStoreActions', () => {
const projectPath = '/root/project'; const projectPath = '/root/project';
const dismissEndpoint = '/-/user_callouts'; const dismissEndpoint = '/-/user_callouts';
const showSuggestPopover = false; const showSuggestPopover = false;
const useSingleDiffStyle = false;
testAction( testAction(
setBaseConfig, setBaseConfig,
...@@ -85,6 +86,7 @@ describe('DiffsStoreActions', () => { ...@@ -85,6 +86,7 @@ describe('DiffsStoreActions', () => {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
}, },
{ {
endpoint: '', endpoint: '',
...@@ -93,6 +95,7 @@ describe('DiffsStoreActions', () => { ...@@ -93,6 +95,7 @@ describe('DiffsStoreActions', () => {
projectPath: '', projectPath: '',
dismissEndpoint: '', dismissEndpoint: '',
showSuggestPopover: true, showSuggestPopover: true,
useSingleDiffStyle: true,
}, },
[ [
{ {
...@@ -104,6 +107,7 @@ describe('DiffsStoreActions', () => { ...@@ -104,6 +107,7 @@ describe('DiffsStoreActions', () => {
projectPath, projectPath,
dismissEndpoint, dismissEndpoint,
showSuggestPopover, showSuggestPopover,
useSingleDiffStyle,
}, },
}, },
], ],
......
...@@ -10,11 +10,13 @@ describe('DiffsStoreMutations', () => { ...@@ -10,11 +10,13 @@ describe('DiffsStoreMutations', () => {
const state = {}; const state = {};
const endpoint = '/diffs/endpoint'; const endpoint = '/diffs/endpoint';
const projectPath = '/root/project'; const projectPath = '/root/project';
const useSingleDiffStyle = false;
mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath }); mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath, useSingleDiffStyle });
expect(state.endpoint).toEqual(endpoint); expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath); expect(state.projectPath).toEqual(projectPath);
expect(state.useSingleDiffStyle).toEqual(useSingleDiffStyle);
}); });
}); });
......
...@@ -721,6 +721,28 @@ describe('common_utils', () => { ...@@ -721,6 +721,28 @@ describe('common_utils', () => {
}); });
}); });
describe('convertObjectPropsToSnakeCase', () => {
it('converts each object key to snake case', () => {
const obj = {
some: 'some',
'cool object': 'cool object',
likeThisLongOne: 'likeThisLongOne',
};
expect(commonUtils.convertObjectPropsToSnakeCase(obj)).toEqual({
some: 'some',
cool_object: 'cool object',
like_this_long_one: 'likeThisLongOne',
});
});
it('returns an empty object if there are no keys', () => {
['', {}, [], null].forEach(badObj => {
expect(commonUtils.convertObjectPropsToSnakeCase(badObj)).toEqual({});
});
});
});
describe('with options', () => { describe('with options', () => {
const objWithoutChildren = { const objWithoutChildren = {
project_name: 'GitLab CE', project_name: 'GitLab CE',
......
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