Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-09-15 12:09:30 +00:00
parent 03c7356304
commit 33212c8ff1
316 changed files with 3030 additions and 822 deletions

View File

@ -263,13 +263,13 @@ export default {
commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId });
const { boardId } = state.endpoints;
const [groupPath, project] = issuePath.split(/[/#]/);
const [fullProjectPath] = issuePath.split(/[#]/);
gqlClient
.mutate({
mutation: issueMoveListMutation,
variables: {
projectPath: `${groupPath}/${project}`,
projectPath: fullProjectPath,
boardId: fullBoardId(boardId),
iid: issueIid,
fromListId: getIdFromGraphQLId(fromListId),

View File

@ -1,8 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
import { GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import DiffTableCell from './diff_table_cell.vue';
import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import {
MATCH_LINE_TYPE,
NEW_LINE_TYPE,
@ -13,11 +12,16 @@ import {
PARALLEL_DIFF_VIEW_TYPE,
NEW_NO_NEW_LINE_TYPE,
EMPTY_CELL_TYPE,
LINE_HOVER_CLASS_NAME,
} from '../constants';
import { __ } from '~/locale';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
import DiffGutterAvatars from './diff_gutter_avatars.vue';
export default {
components: {
DiffTableCell,
GlIcon,
DiffGutterAvatars,
},
directives: {
GlTooltip: GlTooltipDirective,
@ -51,10 +55,12 @@ export default {
return {
isLeftHover: false,
isRightHover: false,
isCommentButtonRendered: false,
};
},
computed: {
...mapGetters('diffs', ['fileLineCoverage']),
...mapGetters(['isLoggedIn']),
...mapState({
isHighlighted(state) {
if (this.isCommented) return true;
@ -66,12 +72,15 @@ export default {
return lineCode ? lineCode === state.diffs.highlightedRow : false;
},
}),
isContextLine() {
isContextLineLeft() {
return this.line.left && this.line.left.type === CONTEXT_LINE_TYPE;
},
isContextLineRight() {
return this.line.right && this.line.right.type === CONTEXT_LINE_TYPE;
},
classNameMap() {
return {
[CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
[CONTEXT_LINE_CLASS_NAME]: this.isContextLineLeft,
[PARALLEL_DIFF_VIEW_TYPE]: true,
};
},
@ -98,6 +107,129 @@ export default {
coverageState() {
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
classNameMapCellLeft() {
const { type } = this.line.left;
return [
type,
{
hll: this.isHighlighted,
[LINE_HOVER_CLASS_NAME]:
this.isLoggedIn && this.isLeftHover && !this.isContextLineLeft && !this.isMetaLineLeft,
},
];
},
classNameMapCellRight() {
const { type } = this.line.right;
return [
type,
{
hll: this.isHighlighted,
[LINE_HOVER_CLASS_NAME]:
this.isLoggedIn &&
this.isRightHover &&
!this.isContextLineRight &&
!this.isMetaLineRight,
},
];
},
addCommentTooltipLeft() {
const brokenSymlinks = this.line.left.commentsDisabled;
let tooltip = __('Add a comment to this line');
if (brokenSymlinks) {
if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
tooltip = __(
'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
);
} else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
tooltip = __(
'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
);
}
}
return tooltip;
},
addCommentTooltipRight() {
const brokenSymlinks = this.line.right.commentsDisabled;
let tooltip = __('Add a comment to this line');
if (brokenSymlinks) {
if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
tooltip = __(
'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
);
} else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
tooltip = __(
'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
);
}
}
return tooltip;
},
shouldRenderCommentButton() {
if (!this.isCommentButtonRendered) {
return false;
}
if (this.isLoggedIn) {
const isDiffHead = parseBoolean(getParameterByName('diff_head'));
return !isDiffHead || gon.features?.mergeRefHeadComments;
}
return false;
},
shouldShowCommentButtonLeft() {
return (
this.isLeftHover &&
!this.isContextLineLeft &&
!this.isMetaLineLeft &&
!this.hasDiscussionsLeft
);
},
shouldShowCommentButtonRight() {
return (
this.isRightHover &&
!this.isContextLineRight &&
!this.isMetaLineRight &&
!this.hasDiscussionsRight
);
},
hasDiscussionsLeft() {
return this.line.left.discussions && this.line.left.discussions.length > 0;
},
hasDiscussionsRight() {
return this.line.right.discussions && this.line.right.discussions.length > 0;
},
lineHrefOld() {
return `#${this.line.left.line_code || ''}`;
},
lineHrefNew() {
return `#${this.line.right.line_code || ''}`;
},
lineCode() {
return (
(this.line.left && this.line.left.line_code) ||
(this.line.right && this.line.right.line_code)
);
},
isMetaLineLeft() {
const { type } = this.line.left;
return (
type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE || type === EMPTY_CELL_TYPE
);
},
isMetaLineRight() {
const { type } = this.line.right;
return (
type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE || type === EMPTY_CELL_TYPE
);
},
},
created() {
this.newLineType = NEW_LINE_TYPE;
@ -106,9 +238,26 @@ export default {
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
this.unwatchShouldShowCommentButton = this.$watch(
vm => [vm.shouldShowCommentButtonLeft, vm.shouldShowCommentButtonRight].join(),
newVal => {
if (newVal) {
this.isCommentButtonRendered = true;
this.unwatchShouldShowCommentButton();
}
},
);
},
beforeDestroy() {
this.unwatchShouldShowCommentButton();
},
methods: {
...mapActions('diffs', ['scrollToLineIfNeededParallel']),
...mapActions('diffs', [
'scrollToLineIfNeededParallel',
'showCommentForm',
'setHighlightedRow',
'toggleLineDiscussions',
]),
handleMouseMove(e) {
const isHover = e.type === 'mouseover';
const hoveringCell = e.target.closest('td');
@ -134,6 +283,9 @@ export default {
table.addClass(`${lineClass}-selected`);
}
},
handleCommentButton(line) {
this.showCommentForm({ lineCode: line.line_code, fileHash: this.fileHash });
},
},
};
</script>
@ -146,18 +298,46 @@ export default {
@mouseout="handleMouseMove"
>
<template v-if="line.left && !isMatchLineLeft">
<diff-table-cell
:file-hash="fileHash"
:line="line.left"
:line-type="oldLineType"
:is-bottom="isBottom"
:is-hover="isLeftHover"
:is-highlighted="isHighlighted"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
line-position="left"
class="diff-line-num old_line"
/>
<td ref="oldTd" :class="classNameMapCellLeft" class="diff-line-num old_line">
<span
v-if="shouldRenderCommentButton"
ref="addNoteTooltipLeft"
v-gl-tooltip
class="add-diff-note tooltip-wrapper"
:title="addCommentTooltipLeft"
>
<button
v-show="shouldShowCommentButtonLeft"
ref="addDiffNoteButtonLeft"
type="button"
class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
:disabled="line.left.commentsDisabled"
@click="handleCommentButton(line.left)"
>
<gl-icon :size="12" name="comment" />
</button>
</span>
<a
v-if="line.left.old_line"
ref="lineNumberRefOld"
:data-linenumber="line.left.old_line"
:href="lineHrefOld"
@click="setHighlightedRow(lineCode)"
>
</a>
<diff-gutter-avatars
v-if="hasDiscussionsLeft"
:discussions="line.left.discussions"
:discussions-expanded="line.left.discussionsExpanded"
@toggleLineDiscussions="
toggleLineDiscussions({
lineCode: line.left.line_code,
fileHash,
expanded: !line.left.discussionsExpanded,
})
"
/>
</td>
<td :class="parallelViewLeftLineType" class="line-coverage left-side"></td>
<td
:id="line.left.line_code"
@ -173,18 +353,46 @@ export default {
<td class="line_content with-coverage parallel left-side empty-cell"></td>
</template>
<template v-if="line.right && !isMatchLineRight">
<diff-table-cell
:file-hash="fileHash"
:line="line.right"
:line-type="newLineType"
:is-bottom="isBottom"
:is-hover="isRightHover"
:is-highlighted="isHighlighted"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
line-position="right"
class="diff-line-num new_line"
/>
<td ref="newTd" :class="classNameMapCellRight" class="diff-line-num new_line">
<span
v-if="shouldRenderCommentButton"
ref="addNoteTooltipRight"
v-gl-tooltip
class="add-diff-note tooltip-wrapper"
:title="addCommentTooltipRight"
>
<button
v-show="shouldShowCommentButtonRight"
ref="addDiffNoteButtonRight"
type="button"
class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
:disabled="line.right.commentsDisabled"
@click="handleCommentButton(line.right)"
>
<gl-icon :size="12" name="comment" />
</button>
</span>
<a
v-if="line.right.new_line"
ref="lineNumberRefNew"
:data-linenumber="line.right.new_line"
:href="lineHrefNew"
@click="setHighlightedRow(lineCode)"
>
</a>
<diff-gutter-avatars
v-if="hasDiscussionsRight"
:discussions="line.right.discussions"
:discussions-expanded="line.right.discussionsExpanded"
@toggleLineDiscussions="
toggleLineDiscussions({
lineCode: line.right.line_code,
fileHash,
expanded: !line.right.discussionsExpanded,
})
"
/>
</td>
<td
v-gl-tooltip.hover
:title="coverageState.text"

View File

@ -468,7 +468,6 @@ export default {
<component
:is="descriptionComponent"
v-if="state.descriptionHtml"
:can-update="canUpdate"
:description-html="state.descriptionHtml"
:description-text="state.descriptionText"

View File

@ -0,0 +1,20 @@
query getAlert($iid: String!, $fullPath: ID!) {
project(fullPath: $fullPath) {
issue(iid: $iid) {
alertManagementAlert {
iid
title
detailsUrl
severity
status
startedAt
eventCount
monitoringTool
service
description
endedAt
details
}
}
}
}

View File

@ -1,28 +1,20 @@
<script>
import { GlLink } from '@gitlab/ui';
import { formatDate } from '~/lib/utils/datetime_utility';
import getHighlightBarInfo from './graphql/queries/get_highlight_bar_info.graphql';
export default {
components: {
GlLink,
},
inject: ['fullPath', 'iid'],
apollo: {
props: {
alert: {
query: getHighlightBarInfo,
variables() {
return {
fullPath: this.fullPath,
iid: this.iid,
};
},
update: data => data.project?.issue?.alertManagementAlert,
type: Object,
required: true,
},
},
computed: {
startTime() {
return formatDate(this.alert.createdAt, 'yyyy-mm-dd Z');
return formatDate(this.alert.startedAt, 'yyyy-mm-dd Z');
},
},
};
@ -30,7 +22,6 @@ export default {
<template>
<div
v-if="alert"
class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between"
>
<div class="text-truncate gl-pr-3">

View File

@ -1,12 +0,0 @@
query getHighlightBarInfo($iid: String!, $fullPath: ID!) {
project(fullPath: $fullPath) {
issue(iid: $iid) {
alertManagementAlert {
title
detailsUrl
createdAt
eventCount
}
}
}
}

View File

@ -1,25 +1,71 @@
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
import DescriptionComponent from '../description.vue';
import HighlightBar from './highlight_bar/higlight_bar.vue';
import HighlightBar from './highlight_bar.vue';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import getAlert from './graphql/queries/get_alert.graphql';
export default {
components: {
AlertDetailsTable,
DescriptionComponent,
GlTab,
GlTabs,
DescriptionComponent,
HighlightBar,
},
inject: ['fullPath', 'iid'],
apollo: {
alert: {
query: getAlert,
variables() {
return {
fullPath: this.fullPath,
iid: this.iid,
};
},
update(data) {
return data?.project?.issue?.alertManagementAlert;
},
error() {
createFlash({
message: s__('Incident|There was an issue loading alert data. Please try again.'),
});
},
},
},
data() {
return {
alert: null,
};
},
computed: {
loading() {
return this.$apollo.queries.alert.loading;
},
alertTableFields() {
if (this.alert) {
const { detailsUrl, __typename, ...restDetails } = this.alert;
return restDetails;
}
return null;
},
},
};
</script>
<template>
<div>
<gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
<gl-tab :title="__('Summary')">
<highlight-bar />
<gl-tab :title="s__('Incident|Summary')">
<highlight-bar v-if="alert" :alert="alert" />
<description-component v-bind="$attrs" />
</gl-tab>
<gl-tab v-if="alert" class="alert-management-details" :title="s__('Incident|Alert details')">
<alert-details-table :alert="alertTableFields" :loading="loading" />
</gl-tab>
</gl-tabs>
</div>
</template>

View File

@ -1,6 +1,5 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { GlButton, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
@ -10,6 +9,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml,
},
mixins: [animateMixin],
props: {
@ -65,13 +65,13 @@ export default {
<template>
<div class="title-container">
<h2
v-safe-html="titleHtml"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="title qa-title"
dir="auto"
v-html="titleHtml"
></h2>
<gl-button
v-if="showInlineEditButton && canUpdate"

View File

@ -1,10 +1,11 @@
<script>
import { mapState, mapGetters } from 'vuex';
import { GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import PackageTags from '../../shared/components/package_tags.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import { __ } from '~/locale';
export default {
@ -12,9 +13,9 @@ export default {
components: {
TitleArea,
GlIcon,
GlLink,
GlSprintf,
PackageTags,
MetadataItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@ -54,35 +55,24 @@ export default {
</template>
<template v-if="packageTypeDisplay" #metadata_type>
<gl-icon name="package" class="gl-text-gray-500 gl-mr-3" />
<span data-testid="package-type" class="gl-font-weight-bold">{{ packageTypeDisplay }}</span>
<metadata-item data-testid="package-type" icon="package" :text="packageTypeDisplay" />
</template>
<template #metadata_size>
<gl-icon name="disk" class="gl-text-gray-500 gl-mr-3" />
<span data-testid="package-size" class="gl-font-weight-bold">{{ totalSize }}</span>
<metadata-item data-testid="package-size" icon="disk" :text="totalSize" />
</template>
<template v-if="packagePipeline" #metadata_pipeline>
<gl-icon name="review-list" class="gl-text-gray-500 gl-mr-3" />
<gl-link
<metadata-item
data-testid="pipeline-project"
:href="packagePipeline.project.web_url"
class="gl-font-weight-bold gl-str-truncated"
>
{{ packagePipeline.project.name }}
</gl-link>
icon="review-list"
:text="packagePipeline.project.name"
:link="packagePipeline.project.web_url"
/>
</template>
<template v-if="packagePipeline" #metadata_ref>
<gl-icon name="branch" data-testid="package-ref-icon" class="gl-text-gray-500 gl-mr-3" />
<span
v-gl-tooltip
data-testid="package-ref"
class="gl-font-weight-bold gl-str-truncated mw-xs"
:title="packagePipeline.ref"
>{{ packagePipeline.ref }}</span
>
<metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
</template>
<template v-if="hasTagsToDisplay" #metadata_tags>

View File

@ -1,7 +1,8 @@
<script>
import { GlSprintf, GlLink, GlIcon } from '@gitlab/ui';
import { GlSprintf, GlLink } from '@gitlab/ui';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { n__ } from '~/locale';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import { n__, sprintf } from '~/locale';
import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import {
@ -14,10 +15,10 @@ import {
export default {
components: {
GlIcon,
GlSprintf,
GlLink,
TitleArea,
MetadataItem,
},
props: {
expirationPolicy: {
@ -58,11 +59,12 @@ export default {
},
computed: {
imagesCountText() {
return n__(
const pluralisedString = n__(
'ContainerRegistry|%{count} Image repository',
'ContainerRegistry|%{count} Image repositories',
this.imagesCount,
);
return sprintf(pluralisedString, { count: this.imagesCount });
},
timeTillRun() {
const difference = calculateRemainingMilliseconds(this.expirationPolicy?.next_run_at);
@ -73,7 +75,7 @@ export default {
},
expirationPolicyText() {
return this.expirationPolicyEnabled
? EXPIRATION_POLICY_WILL_RUN_IN
? sprintf(EXPIRATION_POLICY_WILL_RUN_IN, { time: this.timeTillRun })
: EXPIRATION_POLICY_DISABLED_TEXT;
},
showExpirationPolicyTip() {
@ -92,24 +94,21 @@ export default {
<slot name="commands"></slot>
</template>
<template #metadata_count>
<span v-if="imagesCount" data-testid="images-count">
<gl-icon class="gl-mr-1" name="container-image" />
<gl-sprintf :message="imagesCountText">
<template #count>
{{ imagesCount }}
</template>
</gl-sprintf>
</span>
<metadata-item
v-if="imagesCount"
data-testid="images-count"
icon="container-image"
:text="imagesCountText"
/>
</template>
<template #metadata_exp_policies>
<span v-if="!hideExpirationPolicyData" data-testid="expiration-policy">
<gl-icon class="gl-mr-1" name="expire" />
<gl-sprintf :message="expirationPolicyText">
<template #time>
{{ timeTillRun }}
</template>
</gl-sprintf>
</span>
<metadata-item
v-if="!hideExpirationPolicyData"
data-testid="expiration-policy"
icon="expire"
:text="expirationPolicyText"
size="xl"
/>
</template>
</title-area>

View File

@ -19,7 +19,7 @@ export default {
},
},
tableHeader: {
[s__('AlertManagement|Full Alert Payload')]: s__('AlertManagement|Value'),
[s__('AlertManagement|Key')]: s__('AlertManagement|Value'),
},
computed: {
items() {
@ -33,7 +33,7 @@ export default {
</script>
<template>
<gl-table
class="alert-management-details-table"
class="alert-management-details-table gl-mb-0!"
:busy="loading"
:empty-text="s__('AlertManagement|No alert data to display.')"
:items="items"

View File

@ -0,0 +1,63 @@
<script>
import { GlIcon, GlLink } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
export default {
name: 'MetadataItem',
components: {
GlIcon,
GlLink,
TooltipOnTruncate,
},
props: {
icon: {
type: String,
required: false,
default: null,
},
text: {
type: String,
required: true,
},
link: {
type: String,
required: false,
default: '',
},
size: {
type: String,
required: false,
default: 's',
validator(value) {
return !value || ['xs', 's', 'm', 'l', 'xl'].includes(value);
},
},
},
computed: {
sizeClass() {
return `mw-${this.size}`;
},
},
};
</script>
<template>
<div class="gl-display-inline-flex gl-align-items-center">
<gl-icon v-if="icon" :name="icon" class="gl-text-gray-500 gl-mr-3" />
<tooltip-on-truncate v-if="link" :title="text" class="gl-text-truncate" :class="sizeClass">
<gl-link :href="link" class="gl-font-weight-bold">
{{ text }}
</gl-link>
</tooltip-on-truncate>
<div
v-else
data-testid="metadata-item-text"
class="gl-font-weight-bold gl-display-inline-flex"
:class="sizeClass"
>
<tooltip-on-truncate :title="text" class="gl-text-truncate">
{{ text }}
</tooltip-on-truncate>
</div>
</div>
</template>

View File

@ -6,7 +6,10 @@
@include gl-border-0;
@include gl-p-5;
border-color: transparent;
border-bottom: 1px solid $table-border-color;
&:not(:last-child) {
border-bottom: 1px solid $table-border-color;
}
&:first-child {
div {
@ -31,6 +34,12 @@
}
}
}
&:last-child {
&::after {
content: none !important;
}
}
}
}

View File

@ -178,7 +178,6 @@ $status-box-line-height: 26px;
.milestone-detail {
border-bottom: 1px solid $border-color;
padding: 20px 0;
}
@include media-breakpoint-down(xs) {

View File

@ -46,7 +46,7 @@ module Repositories
end
def download_objects!
existing_oids = project.all_lfs_objects_oids(oids: objects_oids)
existing_oids = project.lfs_objects_oids(oids: objects_oids)
objects.each do |object|
if existing_oids.include?(object[:oid])

View File

@ -6,6 +6,8 @@ module Types
graphql_name 'AlertManagementAlert'
description "Describes an alert from the project's Alert Management"
present_using ::AlertManagement::AlertPresenter
implements(Types::Notes::NoteableType)
authorize :read_alert_management_alert
@ -120,10 +122,6 @@ module Types
def notes
object.ordered_notes
end
def runbook
object.parsed_payload.runbook
end
end
end
end

View File

@ -58,10 +58,6 @@ module DashboardHelper
links += [:activity, :milestones]
end
if can?(current_user, :read_instance_statistics)
links << :analytics
end
links
end
end

View File

@ -47,7 +47,7 @@ module NavHelper
end
def has_extra_nav_icons?
Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics) || current_user.admin?
Gitlab::Sherlock.enabled? || current_user.admin?
end
def page_has_markdown?

View File

@ -118,7 +118,7 @@ module AlertManagement
end
delegate :iid, to: :issue, prefix: true, allow_nil: true
delegate :metrics_dashboard_url, :details_url, :details, to: :present
delegate :details_url, to: :present
scope :for_iid, -> (iid) { where(iid: iid) }
scope :for_status, -> (status) { where(status: status) }
@ -218,12 +218,6 @@ module AlertManagement
end
end
def present
return super(presenter_class: AlertManagement::PrometheusAlertPresenter) if prometheus?
super
end
private
def hook_data

View File

@ -1469,46 +1469,6 @@ class Project < ApplicationRecord
forked_from_project || fork_network&.root_project
end
# TODO: Remove this method once all LfsObjectsProject records are backfilled
# for forks.
#
# See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
def lfs_storage_project
@lfs_storage_project ||= begin
result = self
# TODO: Make this go to the fork_network root immediately
# dependant on the discussion in: https://gitlab.com/gitlab-org/gitlab-foss/issues/39769
result = result.fork_source while result&.forked?
result || self
end
end
# This will return all `lfs_objects` that are accessible to the project and
# the fork source. This is needed since older forks won't have access to some
# LFS objects directly and have to get it from the fork source.
#
# TODO: Remove this method once all LfsObjectsProject records are backfilled
# for forks. At that point, projects can look at their own `lfs_objects`.
#
# See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
def all_lfs_objects
LfsObject
.distinct
.joins(:lfs_objects_projects)
.where(lfs_objects_projects: { project_id: [self, lfs_storage_project] })
end
# TODO: Remove this method once all LfsObjectsProject records are backfilled
# for forks. At that point, projects can look at their own `lfs_objects` so
# `lfs_objects_oids` can be used instead.
#
# See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
def all_lfs_objects_oids(oids: [])
oids(all_lfs_objects, oids: oids)
end
def lfs_objects_oids(oids: [])
oids(lfs_objects, oids: oids)
end

View File

@ -98,7 +98,6 @@ class GlobalPolicy < BasePolicy
rule { admin }.policy do
enable :read_custom_attribute
enable :update_custom_attribute
enable :read_instance_statistics
end
# We can't use `read_statistics` because the user may have different permissions for different projects

View File

@ -6,7 +6,10 @@ module AlertManagement
include IncidentManagement::Settings
include ActionView::Helpers::UrlHelper
MARKDOWN_LINE_BREAK = " \n".freeze
MARKDOWN_LINE_BREAK = " \n"
HORIZONTAL_LINE = "\n\n---\n\n"
delegate :metrics_dashboard_url, :runbook, to: :parsed_payload
def initialize(alert, _attributes = {})
super
@ -16,28 +19,17 @@ module AlertManagement
end
def issue_description
horizontal_line = "\n\n---\n\n"
[
issue_summary_markdown,
alert_markdown,
incident_management_setting.issue_template_content
].compact.join(horizontal_line)
].compact.join(HORIZONTAL_LINE)
end
def start_time
started_at&.strftime('%d %B %Y, %-l:%M%p (%Z)')
end
def issue_summary_markdown
<<~MARKDOWN.chomp
#{metadata_list}
#{alert_details}#{metric_embed_for_alert}
MARKDOWN
end
def metrics_dashboard_url; end
def details_url
details_project_alert_management_url(project, alert.iid)
end
@ -49,15 +41,15 @@ module AlertManagement
private
attr_reader :alert, :project
delegate :alert_markdown, :full_query, to: :parsed_payload
def alerting_alert
strong_memoize(:alerting_alert) do
Gitlab::Alerting::Alert.new(project: project, payload: alert.payload).present
end
def issue_summary_markdown
<<~MARKDOWN.chomp
#{metadata_list}
#{alert_details}#{metric_embed_for_alert}
MARKDOWN
end
def alert_markdown; end
def metadata_list
metadata = []
@ -90,9 +82,9 @@ module AlertManagement
.join(MARKDOWN_LINE_BREAK)
end
def metric_embed_for_alert; end
def full_query; end
def metric_embed_for_alert
"\n[](#{metrics_dashboard_url})" if metrics_dashboard_url
end
def list_item(key, value)
"**#{key}:** #{value}".strip

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
module AlertManagement
class PrometheusAlertPresenter < AlertManagement::AlertPresenter
def metrics_dashboard_url
alerting_alert.metrics_dashboard_url
end
private
def alert_markdown
alerting_alert.alert_markdown
end
def metric_embed_for_alert
alerting_alert.metric_embed_for_alert
end
def full_query
alerting_alert.full_query
end
end
end

View File

@ -42,11 +42,37 @@ module Projects
end
def process_existing_alert(alert)
alert.register_new_event!
if am_alert_params[:ended_at].present?
process_resolved_alert(alert)
else
alert.register_new_event!
end
alert
end
def process_resolved_alert(alert)
return unless auto_close_incident?
if alert.resolve(am_alert_params[:ended_at])
close_issue(alert.issue)
end
alert
end
def close_issue(issue)
return if issue.blank? || issue.closed?
::Issues::CloseService
.new(project, User.alert_bot)
.execute(issue, system_note: false)
SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
end
def create_alert
alert = AlertManagement::Alert.create(am_alert_params)
alert = AlertManagement::Alert.create(am_alert_params.except(:ended_at))
alert.execute_services if alert.persisted?
SystemNoteService.create_new_alert(alert, 'Generic Alert Endpoint')

View File

@ -6,6 +6,9 @@ module Projects
class LfsDownloadService < BaseService
SizeError = Class.new(StandardError)
OidError = Class.new(StandardError)
ResponseError = Class.new(StandardError)
LARGE_FILE_SIZE = 1.megabytes
attr_reader :lfs_download_object
delegate :oid, :size, :credentials, :sanitized_url, to: :lfs_download_object, prefix: :lfs
@ -19,6 +22,7 @@ module Projects
def execute
return unless project&.lfs_enabled? && lfs_download_object
return error("LFS file with oid #{lfs_oid} has invalid attributes") unless lfs_download_object.valid?
return link_existing_lfs_object! if Feature.enabled?(:lfs_link_existing_object, project, default_enabled: true) && lfs_size > LARGE_FILE_SIZE && lfs_object
wrap_download_errors do
download_lfs_file!
@ -29,7 +33,7 @@ module Projects
def wrap_download_errors(&block)
yield
rescue SizeError, OidError, StandardError => e
rescue SizeError, OidError, ResponseError, StandardError => e
error("LFS file with oid #{lfs_oid} could't be downloaded from #{lfs_sanitized_url}: #{e.message}")
end
@ -56,15 +60,13 @@ module Projects
def download_and_save_file!(file)
digester = Digest::SHA256.new
response = Gitlab::HTTP.get(lfs_sanitized_url, download_headers) do |fragment|
fetch_file do |fragment|
digester << fragment
file.write(fragment)
raise_size_error! if file.size > lfs_size
end
raise StandardError, "Received error code #{response.code}" unless response.success?
raise_size_error! if file.size != lfs_size
raise_oid_error! if digester.hexdigest != lfs_oid
end
@ -78,6 +80,12 @@ module Projects
end
end
def fetch_file(&block)
response = Gitlab::HTTP.get(lfs_sanitized_url, download_headers, &block)
raise ResponseError, "Received error code #{response.code}" unless response.success?
end
def with_tmp_file
create_tmp_storage_dir
@ -123,6 +131,29 @@ module Projects
super
end
def lfs_object
@lfs_object ||= LfsObject.find_by_oid(lfs_oid)
end
def link_existing_lfs_object!
existing_file = lfs_object.file.open
buffer_size = 0
result = fetch_file do |fragment|
unless fragment == existing_file.read(fragment.size)
break error("LFS file with oid #{lfs_oid} cannot be linked with an existing LFS object")
end
buffer_size += fragment.size
break success if buffer_size > LARGE_FILE_SIZE
end
project.lfs_objects << lfs_object
result
ensure
existing_file&.close
end
end
end
end

View File

@ -2,21 +2,13 @@
module Projects
class UnlinkForkService < BaseService
# If a fork is given, it:
#
# - Saves LFS objects to the root project
# - Close existing MRs coming from it
# - Is removed from the fork network
#
# If a root of fork(s) is given, it does the same,
# but not updating LFS objects (there'll be no related root to cache it).
# Close existing MRs coming from the project and remove it from the fork network
def execute
fork_network = @project.fork_network
forked_from = @project.forked_from_project
return unless fork_network
save_lfs_objects
merge_requests = fork_network
.merge_requests
.opened
@ -41,7 +33,7 @@ module Projects
# When the project getting out of the network is a node with parent
# and children, both the parent and the node needs a cache refresh.
[@project.forked_from_project, @project].compact.each do |project|
[forked_from, @project].compact.each do |project|
refresh_forks_count(project)
end
end
@ -51,22 +43,5 @@ module Projects
def refresh_forks_count(project)
Projects::ForksCountService.new(project).refresh_cache
end
# TODO: Remove this method once all LfsObjectsProject records are backfilled
# for forks.
#
# See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
def save_lfs_objects
return unless @project.forked?
lfs_storage_project = @project.lfs_storage_project
return unless lfs_storage_project
return if lfs_storage_project == @project # that project is being unlinked
lfs_storage_project.lfs_objects.find_each do |lfs_object|
lfs_object.projects << @project unless lfs_object.projects.include?(@project)
end
end
end
end

View File

@ -24,8 +24,10 @@
- if @group.new_record?
.form-group.row
.offset-sm-2.col-sm-10
.alert.alert-info
= render 'shared/group_tips'
.gl-alert.gl-alert-info
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
= render 'shared/group_tips'
.form-actions
= f.submit _('Create group'), class: "btn btn-success"
= link_to _('Cancel'), admin_groups_path, class: "btn btn-cancel"

View File

@ -1,6 +1,8 @@
- project = local_assigns.fetch(:project)
- return unless project.delete_error.present?
.project-deletion-failed-message.alert.alert-warning
This project was scheduled for deletion, but failed with the following message:
= project.delete_error
.project-deletion-failed-message.gl-alert.gl-alert-warning
= sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
This project was scheduled for deletion, but failed with the following message:
= project.delete_error

View File

@ -2,10 +2,12 @@
- page_title _("Edit"), @blob.path, @ref
- if @conflict
.alert.alert-danger
Someone edited the file the same time you did. Please check out
= link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs.
.gl-alert.gl-alert-danger.gl-mb-5.gl-mt-5
= sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
Someone edited the file the same time you did. Please check out
= link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer', class: 'gl-link'
and make sure your changes will not unintentionally remove theirs.
- if editing_ci_config? && show_web_ide_alert?
#js-suggest-web-ide-ci{ data: { dismiss_endpoint: user_callouts_path, feature_id: UserCalloutsHelper::WEB_IDE_ALERT_DISMISSED, edit_path: ide_edit_path } }

View File

@ -1,8 +1,8 @@
.detail-page-description.milestone-detail
%h2.title{ data: { qa_selector: "milestone_title_content" } }
%h2.gl-m-0{ data: { qa_selector: "milestone_title_content" } }
= markdown_field(milestone, :title)
- if milestone.try(:description).present?
%div{ data: { qa_selector: "milestone_description_content" } }
.description.md
.description.md.gl-px-0.gl-pt-4.gl-border-1.gl-border-t-solid.gl-border-gray-100
= markdown_field(milestone, :description)

View File

@ -13,7 +13,7 @@ class IssuePlacementWorker
QUERY_LIMIT = 100
# rubocop: disable CodeReuse/ActiveRecord
def perform(issue_id)
def perform(issue_id, project_id = nil)
issue = Issue.id_in(issue_id).first
return unless issue

View File

@ -52,7 +52,7 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
def link_lfs_objects(source_project, target_project)
Projects::LfsPointers::LfsLinkService
.new(target_project)
.execute(source_project.all_lfs_objects_oids)
.execute(source_project.lfs_objects_oids)
rescue Projects::LfsPointers::LfsLinkService::TooManyOidsError
raise_fork_failure(
source_project,

View File

@ -0,0 +1,5 @@
---
title: Automatically resolve alert when receiving end time
merge_request: 41648
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Replace bootstrap alerts in app/views/admin/groups/_form.html.haml
merge_request: 41375
author: Gilang Gumilar
type: changed

View File

@ -0,0 +1,5 @@
---
title: Replace bootstrap alerts in app/views/projects/_deletion_failed.html.haml
merge_request: 41344
author: Gilang Gumilar
type: changed

View File

@ -0,0 +1,5 @@
---
title: Replace bootstrap alerts in app/views/projects/blob/edit.html.haml
merge_request: 41298
author: Gilang Gumilar
type: changed

View File

@ -0,0 +1,5 @@
---
title: Update visual styling of container registry metadata
merge_request: 42202
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fix max seats used not updated in billing summary
merge_request: 42184
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Verify only 1mb of existing LFS object to improve LfsDownloadService performance
merge_request: 41770
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Jdb/refactor parallel diff table row
merge_request: 41606
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Fix spacing and borders in milestone title and description
merge_request: 40649
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Surface alert details in a tab on incidents
merge_request: 41850
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Upgrade vendored Dockerfile template to buster
merge_request: 42169
author: Takuya Noguchi
type: other

View File

@ -0,0 +1,7 @@
---
name: additional_snowplow_tracking
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ajax_new_deploy_token
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: allow_group_deploy_token
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: allow_possible_spam
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: allow_unsafe_ruby_regexp
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: api_kaminari_count_with_limit
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: application_settings_tokens_optional_encryption
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: approval_suggestions
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: approvals_commented_by
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: archive_rate_limit
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: artifacts_management_page
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: async_commit_diff_files
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: auto_create_cluster_management_project
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: auto_devops_banner_disabled
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: backfill_partitioned_audit_events
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: batch_suggestions
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: boards_with_swimlanes
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: branch_list_keyset_pagination
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: branch_push_merge_commit_analyze
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: broadcast_issue_updates
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: build_service_proxy
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: builds
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: bulk_update_health_status
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: burnup_charts
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: chatops
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_artifacts_exclude
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_build_metadata_config
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ci_bulk_insert_on_create
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_daily_code_coverage
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_disable_validates_dependencies
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ci_download_daily_code_coverage
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_dynamic_child_pipeline
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_enable_live_trace
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ci_instance_variables_ui
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_job_heartbeats_runner
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_job_jwt
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_key_autocomplete
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_lint_creates_pipeline_with_dry_run
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_pipeline_latest
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_pipeline_rewind_iid
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_pipeline_status_omit_commit_sha_in_cache_key
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_raise_job_rules_without_workflow_rules_warning
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_runners_tokens_optional_encryption
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ci_skip_persistent_ref_existence_check
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: ci_store_pipeline_messages
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_synchronous_artifact_parsing
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_update_queues_for_online_runners
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: ci_yaml_limit_size
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: cleanup_lfs_during_gc
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: cluster_management_project
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: clusters_list_redesign
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: false

View File

@ -0,0 +1,7 @@
---
name: container_registry_api
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: container_registry_cleanup
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: container_registry_fast_tag_delete
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: context_commits
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: create_cloud_run_clusters
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: dashboard_pipeline_status
introduced_by_url:
rollout_issue_url:
group:
type: development
default_enabled: true

Some files were not shown because too many files have changed in this diff Show More