Skip to content

Commit 92ea866

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 991c663 commit 92ea866

File tree

78 files changed

+2759
-514
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2759
-514
lines changed

Gemfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ gem 'thrift', '>= 0.14.0'
323323

324324
# I18n
325325
gem 'ruby_parser', '~> 3.15', require: false
326-
gem 'rails-i18n', '~> 6.0'
326+
gem 'rails-i18n', '~> 7.0'
327327
gem 'gettext_i18n_rails', '~> 1.8.0'
328328
gem 'gettext_i18n_rails_js', '~> 1.3'
329329
gem 'gettext', '~> 3.3', require: false, group: :development
@@ -344,7 +344,7 @@ gem 'prometheus-client-mmap', '~> 0.15.0', require: 'prometheus/client'
344344
gem 'warning', '~> 1.2.0'
345345

346346
group :development do
347-
gem 'lefthook', '~> 1.0.0', require: false
347+
gem 'lefthook', '~> 1.0.1', require: false
348348
gem 'rubocop'
349349
gem 'solargraph', '~> 0.44.3', require: false
350350

Gemfile.lock

+5-5
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ GEM
724724
rest-client (~> 2.0)
725725
launchy (2.5.0)
726726
addressable (~> 2.7)
727-
lefthook (1.0.0)
727+
lefthook (1.0.1)
728728
letter_opener (1.7.0)
729729
launchy (~> 2.2)
730730
letter_opener_web (2.0.0)
@@ -1030,9 +1030,9 @@ GEM
10301030
nokogiri (>= 1.6)
10311031
rails-html-sanitizer (1.4.2)
10321032
loofah (~> 2.3)
1033-
rails-i18n (6.0.0)
1033+
rails-i18n (7.0.3)
10341034
i18n (>= 0.7, < 2)
1035-
railties (>= 6.0.0, < 7)
1035+
railties (>= 6.0.0, < 8)
10361036
railties (6.1.4.7)
10371037
actionpack (= 6.1.4.7)
10381038
activesupport (= 6.1.4.7)
@@ -1586,7 +1586,7 @@ DEPENDENCIES
15861586
knapsack (~> 1.21.1)
15871587
kramdown (~> 2.3.1)
15881588
kubeclient (~> 4.9.2)
1589-
lefthook (~> 1.0.0)
1589+
lefthook (~> 1.0.1)
15901590
letter_opener_web (~> 2.0.0)
15911591
licensee (~> 9.14.1)
15921592
lockbox (~> 0.6.2)
@@ -1650,7 +1650,7 @@ DEPENDENCIES
16501650
rack-timeout (~> 0.6.0)
16511651
rails (~> 6.1.4.7)
16521652
rails-controller-testing
1653-
rails-i18n (~> 6.0)
1653+
rails-i18n (~> 7.0)
16541654
rainbow (~> 3.0)
16551655
rbtrace (~> 0.4)
16561656
rdoc (~> 6.3.2)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<script>
2+
import { GlButton, GlIcon } from '@gitlab/ui';
3+
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/reports/codequality_report/constants';
4+
5+
export default {
6+
components: { GlButton, GlIcon },
7+
props: {
8+
line: {
9+
type: Number,
10+
required: true,
11+
},
12+
codeQuality: {
13+
type: Array,
14+
required: true,
15+
},
16+
},
17+
methods: {
18+
severityClass(severity) {
19+
return SEVERITY_CLASSES[severity] || SEVERITY_CLASSES.unknown;
20+
},
21+
severityIcon(severity) {
22+
return SEVERITY_ICONS[severity] || SEVERITY_ICONS.unknown;
23+
},
24+
},
25+
};
26+
</script>
27+
28+
<template>
29+
<div data-testid="diff-codequality" class="gl-relative">
30+
<ul
31+
class="gl-list-style-none gl-mb-0 gl-p-0 codequality-findings-list gl-border-top-1 gl-border-bottom-1 gl-bg-gray-10"
32+
>
33+
<li
34+
v-for="finding in codeQuality"
35+
:key="finding.description"
36+
class="gl-pt-1 gl-pb-1 gl-pl-3 gl-border-solid gl-border-bottom-0 gl-border-right-0 gl-border-1 gl-border-gray-100"
37+
>
38+
<gl-icon
39+
:size="12"
40+
:name="severityIcon(finding.severity)"
41+
:class="severityClass(finding.severity)"
42+
class="codequality-severity-icon"
43+
/>
44+
{{ finding.description }}
45+
</li>
46+
</ul>
47+
<gl-button
48+
data-testid="diff-codequality-close"
49+
category="tertiary"
50+
size="small"
51+
icon="close"
52+
class="gl-absolute gl-right-2 gl-top-2"
53+
@click="$emit('hideCodeQualityFindings', line)"
54+
/>
55+
</div>
56+
</template>

app/assets/javascripts/diffs/components/diff_row.vue

+6
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ export default {
274274
v-if="$options.showCodequalityLeft(props)"
275275
:codequality="props.line.left.codequality"
276276
:file-path="props.filePath"
277+
@showCodeQualityFindings="
278+
listeners.toggleCodeQualityFindings(props.line.left.codequality[0].line)
279+
"
277280
/>
278281
</div>
279282
<div
@@ -395,6 +398,9 @@ export default {
395398
:codequality="props.line.right.codequality"
396399
:file-path="props.filePath"
397400
data-testid="codeQualityIcon"
401+
@showCodeQualityFindings="
402+
listeners.toggleCodeQualityFindings(props.line.right.codequality[0].line)
403+
"
398404
/>
399405
</div>
400406
<div

app/assets/javascripts/diffs/components/diff_view.vue

+54-9
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
33
import { mapGetters, mapState, mapActions } from 'vuex';
44
import { IdState } from 'vendor/vue-virtual-scroller';
5+
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
56
import DraftNote from '~/batch_comments/components/draft_note.vue';
67
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
78
import { getCommentedLines } from '~/notes/components/multiline_comment_utils';
89
import { hide } from '~/tooltips';
910
import { pickDirection } from '../utils/diff_line';
1011
import DiffCommentCell from './diff_comment_cell.vue';
12+
import DiffCodeQuality from './diff_code_quality.vue';
1113
import DiffExpansionCell from './diff_expansion_cell.vue';
1214
import DiffRow from './diff_row.vue';
1315
import { isHighlighted } from './diff_row_utils';
@@ -17,12 +19,17 @@ export default {
1719
DiffExpansionCell,
1820
DiffRow,
1921
DiffCommentCell,
22+
DiffCodeQuality,
2023
DraftNote,
2124
},
2225
directives: {
2326
SafeHtml,
2427
},
25-
mixins: [draftCommentsMixin, IdState({ idProp: (vm) => vm.diffFile.file_hash })],
28+
mixins: [
29+
draftCommentsMixin,
30+
IdState({ idProp: (vm) => vm.diffFile.file_hash }),
31+
glFeatureFlagsMixin(),
32+
],
2633
props: {
2734
diffFile: {
2835
type: Object,
@@ -43,6 +50,11 @@ export default {
4350
default: false,
4451
},
4552
},
53+
data() {
54+
return {
55+
codeQualityExpandedLines: [],
56+
};
57+
},
4658
idState() {
4759
return {
4860
dragStart: null,
@@ -84,6 +96,23 @@ export default {
8496
}
8597
this.idState.dragStart = line;
8698
},
99+
parseCodeQuality(line) {
100+
return line.left?.codequality ?? line.right.codequality;
101+
},
102+
103+
hideCodeQualityFindings(line) {
104+
const index = this.codeQualityExpandedLines.indexOf(line);
105+
if (index > -1) {
106+
this.codeQualityExpandedLines.splice(index, 1);
107+
}
108+
},
109+
toggleCodeQualityFindings(line) {
110+
if (!this.codeQualityExpandedLines.includes(line)) {
111+
this.codeQualityExpandedLines.push(line);
112+
} else {
113+
this.hideCodeQualityFindings(line);
114+
}
115+
},
87116
onDragOver(line) {
88117
if (line.chunk !== this.idState.dragStart.chunk) return;
89118
@@ -125,15 +154,16 @@ export default {
125154
},
126155
handleParallelLineMouseDown(e) {
127156
const line = e.target.closest('.diff-td');
128-
const table = line.closest('.diff-table');
129-
130-
table.classList.remove('left-side-selected', 'right-side-selected');
131-
const [lineClass] = ['left-side', 'right-side'].filter((name) =>
132-
line.classList.contains(name),
133-
);
157+
if (line) {
158+
const table = line.closest('.diff-table');
159+
table.classList.remove('left-side-selected', 'right-side-selected');
160+
const [lineClass] = ['left-side', 'right-side'].filter((name) =>
161+
line.classList.contains(name),
162+
);
134163
135-
if (lineClass) {
136-
table.classList.add(`${lineClass}-selected`);
164+
if (lineClass) {
165+
table.classList.add(`${lineClass}-selected`);
166+
}
137167
}
138168
},
139169
getCountBetweenIndex(index) {
@@ -148,6 +178,9 @@ export default {
148178
Number(this.diffLines[index - 1].left.new_line)
149179
);
150180
},
181+
getCodeQualityLine(line) {
182+
return this.parseCodeQuality(line)?.[0]?.line;
183+
},
151184
},
152185
userColorScheme: window.gon.user_color_scheme,
153186
};
@@ -190,6 +223,7 @@ export default {
190223
:coverage-loaded="coverageLoaded"
191224
@showCommentForm="(code) => singleLineComment(code, line)"
192225
@setHighlightedRow="setHighlightedRow"
226+
@toggleCodeQualityFindings="toggleCodeQualityFindings"
193227
@toggleLineDiscussions="
194228
({ lineCode, expanded }) =>
195229
toggleLineDiscussions({ lineCode, fileHash: diffFile.file_hash, expanded })
@@ -198,6 +232,17 @@ export default {
198232
@startdragging="onStartDragging"
199233
@stopdragging="onStopDragging"
200234
/>
235+
236+
<diff-code-quality
237+
v-if="
238+
glFeatures.refactorCodeQualityInlineFindings &&
239+
codeQualityExpandedLines.includes(getCodeQualityLine(line))
240+
"
241+
:key="line.line_code"
242+
:line="getCodeQualityLine(line)"
243+
:code-quality="parseCodeQuality(line)"
244+
@hideCodeQualityFindings="hideCodeQualityFindings"
245+
/>
201246
<div
202247
v-if="line.renderCommentRow"
203248
:key="`dcr-${line.line_code || index}`"

app/assets/javascripts/pipeline_wizard/components/input_wrapper.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { isNode, isDocument, isSeq, visit } from 'yaml';
33
import { capitalize } from 'lodash';
44
import TextWidget from '~/pipeline_wizard/components/widgets/text.vue';
55
import ListWidget from '~/pipeline_wizard/components/widgets/list.vue';
6+
import ChecklistWidget from '~/pipeline_wizard/components/widgets/checklist.vue';
67
78
const widgets = {
89
TextWidget,
910
ListWidget,
11+
ChecklistWidget,
1012
};
1113
1214
function isNullOrUndefined(v) {
@@ -30,8 +32,9 @@ export default {
3032
},
3133
target: {
3234
type: String,
33-
required: true,
35+
required: false,
3436
validator: (v) => /^\$.*/g.test(v),
37+
default: null,
3538
},
3639
widget: {
3740
type: String,
@@ -48,6 +51,7 @@ export default {
4851
},
4952
computed: {
5053
path() {
54+
if (!this.target) return null;
5155
let res;
5256
visit(this.template, (seqKey, node, path) => {
5357
if (node && node.value === this.target) {

app/assets/javascripts/pipeline_wizard/components/step.vue

+2-5
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ export default {
3131
inputs: {
3232
type: Array,
3333
required: true,
34-
validator: (value) =>
35-
value.every((i) => {
36-
return i?.target && i?.widget;
37-
}),
34+
validator: (value) => value.every((i) => i?.widget),
3835
},
3936
template: {
4037
type: null,
@@ -131,7 +128,7 @@ export default {
131128
:template="template"
132129
:validate="validate"
133130
:widget="input.widget"
134-
class="gl-mb-2"
131+
class="gl-mb-8"
135132
v-bind="input"
136133
@highlight="onHighlight"
137134
@update:valid="(validationState) => onInputValidationStateChange(i, validationState)"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<script>
2+
import { GlFormGroup, GlFormCheckbox, GlFormCheckboxGroup } from '@gitlab/ui';
3+
import { uniqueId } from 'lodash';
4+
5+
const isValidItemDefinition = (value) => {
6+
// The Item definition should either be a simple string
7+
// or an object with at least a "title" property
8+
return typeof value === 'string' || Boolean(value.text);
9+
};
10+
11+
export default {
12+
name: 'ChecklistWidget',
13+
components: {
14+
GlFormGroup,
15+
GlFormCheckbox,
16+
GlFormCheckboxGroup,
17+
},
18+
props: {
19+
title: {
20+
type: String,
21+
required: false,
22+
default: null,
23+
},
24+
items: {
25+
type: Array,
26+
required: false,
27+
validator: (v) => v.every(isValidItemDefinition),
28+
default: () => [],
29+
},
30+
validate: {
31+
type: Boolean,
32+
required: false,
33+
default: false,
34+
},
35+
},
36+
computed: {
37+
checklistItems() {
38+
return this.items.map((rawItem) => {
39+
const id = rawItem.id || uniqueId();
40+
return {
41+
id,
42+
text: rawItem.text || rawItem,
43+
help: rawItem.help || null,
44+
};
45+
});
46+
},
47+
},
48+
created() {
49+
if (this.items.length > 0) {
50+
this.$emit('update:valid', false);
51+
}
52+
},
53+
methods: {
54+
updateValidState(values) {
55+
this.$emit(
56+
'update:valid',
57+
this.checklistItems.every((item) => values.includes(item.id)),
58+
);
59+
},
60+
},
61+
};
62+
</script>
63+
64+
<template>
65+
<gl-form-group #default="{ ariaDescribedby }" :label="title">
66+
<gl-form-checkbox-group :aria-describedby="ariaDescribedby" @input="updateValidState">
67+
<gl-form-checkbox
68+
v-for="item in checklistItems"
69+
:id="item.id"
70+
:key="item.id"
71+
:value="item.id"
72+
>
73+
{{ item.text }}
74+
<template v-if="item.help" #help>
75+
{{ item.help }}
76+
</template>
77+
</gl-form-checkbox>
78+
</gl-form-checkbox-group>
79+
</gl-form-group>
80+
</template>

0 commit comments

Comments
 (0)