Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-26 18:08:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-26 18:08:17 +0300
commitc9d79ef3b5b67792e331a4cc8e6325f3b4a04760 (patch)
tree0b7c48c03e5c59362f975c20fcf84635fddd94e6 /app
parent1691cbe307f7698b3ee39811278990c43b6751a5 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue21
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_list.vue21
-rw-r--r--app/assets/javascripts/alert_management/constants.js27
-rw-r--r--app/assets/javascripts/boards/models/issue.js6
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js10
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue29
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue21
-rw-r--r--app/assets/javascripts/error_tracking/utils.js27
-rw-r--r--app/assets/javascripts/projects/commits/components/author_select.vue4
-rw-r--r--app/assets/stylesheets/pages/storage_quota.scss23
-rw-r--r--app/assets/stylesheets/utilities.scss16
-rw-r--r--app/controllers/concerns/notes_actions.rb6
-rw-r--r--app/finders/resource_milestone_event_finder.rb69
-rw-r--r--app/models/ci/instance_variable.rb5
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/resource_milestone_event.rb10
-rw-r--r--app/services/groups/import_export/export_service.rb6
-rw-r--r--app/services/groups/import_export/import_service.rb5
19 files changed, 270 insertions, 42 deletions
diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
index bb9f092a9ae..c08b4fb2f63 100644
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ b/app/assets/javascripts/alert_management/components/alert_details.vue
@@ -18,10 +18,15 @@ import query from '../graphql/queries/details.query.graphql';
import { fetchPolicies } from '~/lib/graphql';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { ALERTS_SEVERITY_LABELS } from '../constants';
+import {
+ ALERTS_SEVERITY_LABELS,
+ trackAlertsDetailsViewsOptions,
+ trackAlertStatusUpdateOptions,
+} from '../constants';
import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql';
import createIssueQuery from '../graphql/mutations/create_issue_from_alert.graphql';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
+import Tracking from '~/tracking';
export default {
statuses: {
@@ -108,6 +113,9 @@ export default {
return this.errored && !this.isErrorDismissed;
},
},
+ mounted() {
+ this.trackPageViews();
+ },
methods: {
dismissError() {
this.isErrorDismissed = true;
@@ -122,6 +130,9 @@ export default {
projectPath: this.projectPath,
},
})
+ .then(() => {
+ this.trackStatusUpdate(status);
+ })
.catch(() => {
createFlash(
s__(
@@ -157,6 +168,14 @@ export default {
issuePath(issueId) {
return joinPaths(this.projectIssuesPath, issueId);
},
+ trackPageViews() {
+ const { category, action } = trackAlertsDetailsViewsOptions;
+ Tracking.event(category, action);
+ },
+ trackStatusUpdate(status) {
+ const { category, action, label } = trackAlertStatusUpdateOptions;
+ Tracking.event(category, action, { label, property: status });
+ },
},
};
</script>
diff --git a/app/assets/javascripts/alert_management/components/alert_management_list.vue b/app/assets/javascripts/alert_management/components/alert_management_list.vue
index a1a71e592f6..74ce76739a2 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_list.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_list.vue
@@ -19,13 +19,20 @@ import { fetchPolicies } from '~/lib/graphql';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import getAlerts from '../graphql/queries/get_alerts.query.graphql';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
-import { ALERTS_STATUS, ALERTS_STATUS_TABS, ALERTS_SEVERITY_LABELS } from '../constants';
+import {
+ ALERTS_STATUS,
+ ALERTS_STATUS_TABS,
+ ALERTS_SEVERITY_LABELS,
+ trackAlertListViewsOptions,
+ trackAlertStatusUpdateOptions,
+} from '../constants';
import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql';
import { capitalizeFirstCharacter, convertToSnakeCase } from '~/lib/utils/text_utility';
+import Tracking from '~/tracking';
const tdClass = 'table-col d-flex d-md-table-cell align-items-center';
const bodyTrClass =
- 'gl-border-1 gl-border-t-solid gl-border-gray-100 hover-bg-blue-50 hover-gl-cursor-pointer hover-gl-border-b-solid hover-gl-border-blue-200';
+ 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200';
const findDefaultSortColumn = () => document.querySelector('.js-started-at');
export default {
@@ -182,6 +189,7 @@ export default {
},
mounted() {
findDefaultSortColumn().ariaSort = 'ascending';
+ this.trackPageViews();
},
methods: {
filterAlertsByStatus(tabIndex) {
@@ -208,6 +216,7 @@ export default {
},
})
.then(() => {
+ this.trackStatusUpdate(status);
this.$apollo.queries.alerts.refetch();
this.$apollo.queries.alertsCount.refetch();
})
@@ -222,6 +231,14 @@ export default {
navigateToAlertDetails({ iid }) {
return visitUrl(joinPaths(window.location.pathname, iid, 'details'));
},
+ trackPageViews() {
+ const { category, action } = trackAlertListViewsOptions;
+ Tracking.event(category, action);
+ },
+ trackStatusUpdate(status) {
+ const { category, action, label } = trackAlertStatusUpdateOptions;
+ Tracking.event(category, action, { label, property: status });
+ },
},
};
</script>
diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js
index 9df01d9d0b5..a8f5d6cfe30 100644
--- a/app/assets/javascripts/alert_management/constants.js
+++ b/app/assets/javascripts/alert_management/constants.js
@@ -44,3 +44,30 @@ export const ALERTS_STATUS_TABS = [
filters: [ALERTS_STATUS.TRIGGERED, ALERTS_STATUS.ACKNOWLEDGED, ALERTS_STATUS.RESOLVED],
},
];
+
+/* eslint-disable @gitlab/require-i18n-strings */
+
+/**
+ * Tracks snowplow event when user views alerts list
+ */
+export const trackAlertListViewsOptions = {
+ category: 'Alert Management',
+ action: 'view_alerts_list',
+};
+
+/**
+ * Tracks snowplow event when user views alert details
+ */
+export const trackAlertsDetailsViewsOptions = {
+ category: 'Alert Management',
+ action: 'view_alert_details',
+};
+
+/**
+ * Tracks snowplow event when alert status is updated
+ */
+export const trackAlertStatusUpdateOptions = {
+ category: 'Alert Management',
+ action: 'update_alert_status',
+ label: 'Status',
+};
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index 878f49cc6be..02fd0334403 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -60,13 +60,11 @@ class ListIssue {
}
removeAssignee(removeAssignee) {
- if (removeAssignee) {
- this.assignees = this.assignees.filter(assignee => assignee.id !== removeAssignee.id);
- }
+ boardsStore.removeIssueAssignee(this, removeAssignee);
}
removeAllAssignees() {
- this.assignees = [];
+ boardsStore.removeAllIssueAssignees(this);
}
addMilestone(milestone) {
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index fdbd7e89bfb..feef405d52e 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -682,10 +682,20 @@ const boardsStore = {
...this.multiSelect.list.slice(index + 1),
];
},
+ removeIssueAssignee(issue, removeAssignee) {
+ if (removeAssignee) {
+ issue.assignees = issue.assignees.filter(assignee => assignee.id !== removeAssignee.id);
+ }
+ },
clearMultiSelect() {
this.multiSelect.list = [];
},
+
+ removeAllIssueAssignees(issue) {
+ issue.assignees = [];
+ },
+
refreshIssueData(issue, obj) {
issue.id = obj.id;
issue.iid = obj.iid;
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 148edfe3a51..da079877c72 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -20,8 +20,13 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import Stacktrace from './stacktrace.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { trackClickErrorLinkToSentryOptions } from '../utils';
import { severityLevel, severityLevelVariant, errorStatus } from './constants';
+import Tracking from '~/tracking';
+import {
+ trackClickErrorLinkToSentryOptions,
+ trackErrorDetailsViewsOptions,
+ trackErrorStatusUpdateOptions,
+} from '../utils';
import query from '../queries/details.query.graphql';
@@ -172,6 +177,7 @@ export default {
},
},
mounted() {
+ this.trackPageViews();
this.startPollingStacktrace(this.issueStackTracePath);
this.errorPollTimeout = Date.now() + SENTRY_TIMEOUT;
this.$apollo.queries.error.setOptions({
@@ -194,7 +200,10 @@ export default {
onIgnoreStatusUpdate() {
const status =
this.errorStatus === errorStatus.IGNORED ? errorStatus.UNRESOLVED : errorStatus.IGNORED;
- this.updateIgnoreStatus({ endpoint: this.issueUpdatePath, status });
+ // eslint-disable-next-line promise/catch-or-return
+ this.updateIgnoreStatus({ endpoint: this.issueUpdatePath, status }).then(() => {
+ this.trackStatusUpdate(status);
+ });
},
onResolveStatusUpdate() {
const status =
@@ -206,6 +215,7 @@ export default {
if (this.closedIssueId) {
this.isAlertVisible = true;
}
+ this.trackStatusUpdate(status);
});
},
onNoApolloResult() {
@@ -218,6 +228,14 @@ export default {
formatDate(date) {
return `${this.timeFormatted(date)} (${dateFormat(date, 'UTC:yyyy-mm-dd h:MM:ssTT Z')})`;
},
+ trackPageViews() {
+ const { category, action } = trackErrorDetailsViewsOptions;
+ Tracking.event(category, action);
+ },
+ trackStatusUpdate(status) {
+ const { category, action, label } = trackErrorStatusUpdateOptions;
+ Tracking.event(category, action, { label, property: status });
+ },
},
};
</script>
@@ -259,7 +277,7 @@ export default {
<div class="d-inline-flex bv-d-sm-down-none">
<gl-deprecated-button
:loading="updatingIgnoreStatus"
- data-qa-selector="update_ignore_status_button"
+ data-testid="update-ignore-status-btn"
@click="onIgnoreStatusUpdate"
>
{{ ignoreBtnLabel }}
@@ -267,7 +285,7 @@ export default {
<gl-deprecated-button
class="btn-outline-info ml-2"
:loading="updatingResolveStatus"
- data-qa-selector="update_resolve_status_button"
+ data-testid="update-resolve-status-btn"
@click="onResolveStatusUpdate"
>
{{ resolveBtnLabel }}
@@ -275,7 +293,7 @@ export default {
<gl-deprecated-button
v-if="error.gitlabIssuePath"
class="ml-2"
- data-qa-selector="view_issue_button"
+ data-testid="view_issue_button"
:href="error.gitlabIssuePath"
variant="success"
>
@@ -375,6 +393,7 @@ export default {
v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)"
:href="error.externalUrl"
target="_blank"
+ data-testid="external-url-link"
>
<span class="text-truncate">{{ error.externalUrl }}</span>
<icon name="external-link" class="ml-1 flex-shrink-0" />
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index 45432e8ebd8..111b5ad60a5 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -19,6 +19,8 @@ import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { __ } from '~/locale';
import { isEmpty } from 'lodash';
import ErrorTrackingActions from './error_tracking_actions.vue';
+import Tracking from '~/tracking';
+import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '../utils';
export const tableDataClass = 'table-col d-flex d-md-table-cell align-items-center';
@@ -150,6 +152,9 @@ export default {
this.startPolling();
}
},
+ mounted() {
+ this.trackPageViews();
+ },
methods: {
...mapActions('list', [
'startPolling',
@@ -197,13 +202,25 @@ export default {
this.filterValue = label;
return this.filterByStatus(status);
},
- updateIssueStatus({ errorId, status }) {
+ updateErrosStatus({ errorId, status }) {
+ // eslint-disable-next-line promise/catch-or-return
this.updateStatus({
endpoint: this.getIssueUpdatePath(errorId),
status,
+ }).then(() => {
+ this.trackStatusUpdate(status);
});
+
this.removeIgnoredResolvedErrors(errorId);
},
+ trackPageViews() {
+ const { category, action } = trackErrorListViewsOptions;
+ Tracking.event(category, action);
+ },
+ trackStatusUpdate(status) {
+ const { category, action, label } = trackErrorStatusUpdateOptions;
+ Tracking.event(category, action, { label, property: status });
+ },
},
};
</script>
@@ -359,7 +376,7 @@ export default {
</div>
</template>
<template #cell(status)="errors">
- <error-tracking-actions :error="errors.item" @update-issue-status="updateIssueStatus" />
+ <error-tracking-actions :error="errors.item" @update-issue-status="updateErrosStatus" />
</template>
<template #empty>
{{ __('No errors to display.') }}
diff --git a/app/assets/javascripts/error_tracking/utils.js b/app/assets/javascripts/error_tracking/utils.js
index d1cd70a72fa..e519b8ebfe5 100644
--- a/app/assets/javascripts/error_tracking/utils.js
+++ b/app/assets/javascripts/error_tracking/utils.js
@@ -1,4 +1,4 @@
-/* eslint-disable @gitlab/require-i18n-strings, import/prefer-default-export */
+/* eslint-disable @gitlab/require-i18n-strings */
/**
* Tracks snowplow event when User clicks on error link to Sentry
@@ -10,3 +10,28 @@ export const trackClickErrorLinkToSentryOptions = url => ({
label: 'Error Link',
property: url,
});
+
+/**
+ * Tracks snowplow event when user views error list
+ */
+export const trackErrorListViewsOptions = {
+ category: 'Error Tracking',
+ action: 'view_errors_list',
+};
+
+/**
+ * Tracks snowplow event when user views error details
+ */
+export const trackErrorDetailsViewsOptions = {
+ category: 'Error Tracking',
+ action: 'view_error_details',
+};
+
+/**
+ * Tracks snowplow event when error status is updated
+ */
+export const trackErrorStatusUpdateOptions = {
+ category: 'Error Tracking',
+ action: 'update_error_status',
+ label: 'Status',
+};
diff --git a/app/assets/javascripts/projects/commits/components/author_select.vue b/app/assets/javascripts/projects/commits/components/author_select.vue
index eb514b5c070..a8589b50899 100644
--- a/app/assets/javascripts/projects/commits/components/author_select.vue
+++ b/app/assets/javascripts/projects/commits/components/author_select.vue
@@ -110,8 +110,8 @@ export default {
<gl-new-dropdown
:text="dropdownText"
:disabled="hasSearchParam"
- toggle-class="gl-py-3"
- class="gl-dropdown w-100 mt-2 mt-sm-0"
+ toggle-class="gl-py-3 gl-border-0"
+ class="w-100 mt-2 mt-sm-0"
>
<gl-new-dropdown-header>
{{ __('Search by author') }}
diff --git a/app/assets/stylesheets/pages/storage_quota.scss b/app/assets/stylesheets/pages/storage_quota.scss
new file mode 100644
index 00000000000..97ae4f0ade4
--- /dev/null
+++ b/app/assets/stylesheets/pages/storage_quota.scss
@@ -0,0 +1,23 @@
+.storage-type-usage {
+ &:first-child {
+ @include gl-rounded-top-left-base;
+ @include gl-rounded-bottom-left-base;
+ }
+
+ &:last-child {
+ @include gl-rounded-top-right-base;
+ @include gl-rounded-bottom-right-base;
+ }
+
+ &:not(:first-child) {
+ @include gl-border-l-1;
+ @include gl-border-l-solid;
+ @include gl-border-white;
+ }
+
+ &:not(:last-child) {
+ @include gl-border-r-1;
+ @include gl-border-r-solid;
+ @include gl-border-white;
+ }
+}
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 2b51bdd825f..803eac52317 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -87,21 +87,5 @@
}
}
-.gl-shim-h-2 {
- height: px-to-rem(4px);
-}
-
-.gl-shim-w-5 {
- width: px-to-rem(16px);
-}
-
-.gl-shim-pb-3 {
- padding-bottom: 8px;
-}
-
-.gl-shim-pt-5 {
- padding-top: 16px;
-}
-
.gl-text-purple { color: $purple; }
.gl-bg-purple-light { background-color: $purple-light; }
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index d4b0d3b2674..d3dfb1813e4 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -13,9 +13,7 @@ module NotesActions
end
def index
- current_fetched_at = Time.current.to_i
-
- notes_json = { notes: [], last_fetched_at: current_fetched_at }
+ notes_json = { notes: [], last_fetched_at: Time.current.to_i }
notes = notes_finder
.execute
@@ -24,7 +22,7 @@ module NotesActions
if notes_filter != UserPreference::NOTES_FILTERS[:only_comments]
notes =
ResourceEvents::MergeIntoNotesService
- .new(noteable, current_user, last_fetched_at: current_fetched_at)
+ .new(noteable, current_user, last_fetched_at: last_fetched_at)
.execute(notes)
end
diff --git a/app/finders/resource_milestone_event_finder.rb b/app/finders/resource_milestone_event_finder.rb
new file mode 100644
index 00000000000..7af34f0a4bc
--- /dev/null
+++ b/app/finders/resource_milestone_event_finder.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+class ResourceMilestoneEventFinder
+ include FinderMethods
+
+ MAX_PER_PAGE = 100
+
+ attr_reader :params, :current_user, :eventable
+
+ def initialize(current_user, eventable, params = {})
+ @current_user = current_user
+ @eventable = eventable
+ @params = params
+ end
+
+ def execute
+ Kaminari.paginate_array(visible_events)
+ end
+
+ private
+
+ def visible_events
+ @visible_events ||= visible_to_user(events)
+ end
+
+ def events
+ @events ||= eventable.resource_milestone_events.include_relations.page(page).per(per_page)
+ end
+
+ def visible_to_user(events)
+ events.select { |event| visible_for_user?(event) }
+ end
+
+ def visible_for_user?(event)
+ milestone = event_milestones[event.milestone_id]
+ return if milestone.blank?
+
+ parent = milestone.parent
+ parent_availabilities[key_for_parent(parent)]
+ end
+
+ def parent_availabilities
+ @parent_availabilities ||= relevant_parents.to_h do |parent|
+ [key_for_parent(parent), Ability.allowed?(current_user, :read_milestone, parent)]
+ end
+ end
+
+ def key_for_parent(parent)
+ "#{parent.class.name}_#{parent.id}"
+ end
+
+ def event_milestones
+ @milestones ||= events.map(&:milestone).uniq.to_h do |milestone|
+ [milestone.id, milestone]
+ end
+ end
+
+ def relevant_parents
+ @relevant_parents ||= event_milestones.map { |_id, milestone| milestone.parent }
+ end
+
+ def per_page
+ [params[:per_page], MAX_PER_PAGE].compact.min
+ end
+
+ def page
+ params[:page] || 1
+ end
+end
diff --git a/app/models/ci/instance_variable.rb b/app/models/ci/instance_variable.rb
index 557f3a63280..89ace3f7ede 100644
--- a/app/models/ci/instance_variable.rb
+++ b/app/models/ci/instance_variable.rb
@@ -13,6 +13,11 @@ module Ci
message: "(%{value}) has already been taken"
}
+ validates :encrypted_value, length: {
+ maximum: 1024,
+ too_long: 'The encrypted value of the provided variable exceeds %{count} bytes. Variables over 700 characters risk exceeding the limit.'
+ }
+
scope :unprotected, -> { where(protected: false) }
after_commit { self.class.invalidate_memory_cache(:ci_instance_variable_data) }
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 2b072b22454..f37525e56e4 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -401,7 +401,7 @@ module Ci
# The `Ci::Stage` contains all up-to date data
# as atomic processing updates all data in-bulk
stages
- elsif Feature.enabled?(:ci_pipeline_persisted_stages, default_enabled: true) && complete?
+ elsif complete?
# The `Ci::Stage` contains up-to date data only for `completed` pipelines
# this is due to asynchronous processing of pipeline, and stages possibly
# not updated inline with processing of pipeline
diff --git a/app/models/event.rb b/app/models/event.rb
index 12b85697690..25d016291a7 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -21,6 +21,7 @@ class Event < ApplicationRecord
LEFT = 9 # User left project
DESTROYED = 10
EXPIRED = 11 # User left project due to expiry
+ APPROVED = 12
ACTIONS = HashWithIndifferentAccess.new(
created: CREATED,
@@ -33,7 +34,8 @@ class Event < ApplicationRecord
joined: JOINED,
left: LEFT,
destroyed: DESTROYED,
- expired: EXPIRED
+ expired: EXPIRED,
+ approved: APPROVED
).freeze
WIKI_ACTIONS = [CREATED, UPDATED, DESTROYED].freeze
diff --git a/app/models/resource_milestone_event.rb b/app/models/resource_milestone_event.rb
index 039f26d8e3f..36068cf508b 100644
--- a/app/models/resource_milestone_event.rb
+++ b/app/models/resource_milestone_event.rb
@@ -9,6 +9,8 @@ class ResourceMilestoneEvent < ResourceEvent
validate :exactly_one_issuable
+ scope :include_relations, -> { includes(:user, milestone: [:project, :group]) }
+
enum action: {
add: 1,
remove: 2
@@ -26,4 +28,12 @@ class ResourceMilestoneEvent < ResourceEvent
def milestone_title
milestone&.title
end
+
+ def milestone_parent
+ milestone&.parent
+ end
+
+ def issuable
+ issue || merge_request
+ end
end
diff --git a/app/services/groups/import_export/export_service.rb b/app/services/groups/import_export/export_service.rb
index 39a6889fc84..abac0ffc5d9 100644
--- a/app/services/groups/import_export/export_service.rb
+++ b/app/services/groups/import_export/export_service.rb
@@ -22,7 +22,7 @@ module Groups
save!
ensure
- cleanup
+ remove_base_tmp_dir
end
private
@@ -81,8 +81,8 @@ module Groups
Gitlab::ImportExport::Saver.new(exportable: @group, shared: @shared)
end
- def cleanup
- FileUtils.rm_rf(shared.archive_path) if shared&.archive_path
+ def remove_base_tmp_dir
+ FileUtils.rm_rf(shared.base_path) if shared&.base_path
end
def notify_error!
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index dcd78210801..bd611d55847 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -26,6 +26,7 @@ module Groups
end
ensure
+ remove_base_tmp_dir
remove_import_file
end
@@ -102,6 +103,10 @@ module Groups
raise Gitlab::ImportExport::Error.new(@shared.errors.to_sentence)
end
+
+ def remove_base_tmp_dir
+ FileUtils.rm_rf(@shared.base_path)
+ end
end
end
end