Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4f8ecdd7a9
commit
8577a60062
|
|
@ -1 +1 @@
|
|||
46b9580af93104de9b4c1d3dda81e9aaf7eb4c01
|
||||
5261aae488f191a1373243d2f9ca000255477d7e
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ export default {
|
|||
transformFluxResourceData(item) {
|
||||
return {
|
||||
name: item.metadata.name,
|
||||
namespace: item.metadata.namespace,
|
||||
status: fluxSyncStatus(item.status.conditions).status,
|
||||
labels: item.metadata.labels,
|
||||
annotations: item.metadata.annotations,
|
||||
|
|
@ -354,6 +355,7 @@ export default {
|
|||
<workload-details
|
||||
v-if="hasSelectedItem"
|
||||
:item="selectedItem"
|
||||
:configuration="k8sAccessConfiguration"
|
||||
@delete-pod="onDeletePod"
|
||||
@flux-reconcile="onFluxReconcile"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import k8sDeploymentsQuery from './queries/k8s_deployments.query.graphql';
|
|||
import k8sNamespacesQuery from './queries/k8s_namespaces.query.graphql';
|
||||
import fluxKustomizationQuery from './queries/flux_kustomization.query.graphql';
|
||||
import fluxHelmReleaseQuery from './queries/flux_helm_release.query.graphql';
|
||||
import k8sEventsQuery from './queries/k8s_events.query.graphql';
|
||||
import { resolvers } from './resolvers';
|
||||
import typeDefs from './typedefs.graphql';
|
||||
import { connectionStatus } from './resolvers/kubernetes/constants';
|
||||
|
|
@ -170,6 +171,17 @@ export const apolloProvider = (endpoint) => {
|
|||
data: { logs: [] },
|
||||
});
|
||||
|
||||
cache.writeQuery({
|
||||
query: k8sEventsQuery,
|
||||
data: {
|
||||
lastTimestamp: '',
|
||||
message: '',
|
||||
reason: '',
|
||||
source: {},
|
||||
type: '',
|
||||
},
|
||||
});
|
||||
|
||||
return new VueApollo({
|
||||
defaultClient,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
query getK8sEvents(
|
||||
$configuration: K8sDashboardConfig
|
||||
$involvedObjectName: String
|
||||
$namespace: String
|
||||
) {
|
||||
k8sEvents(
|
||||
configuration: $configuration
|
||||
involvedObjectName: $involvedObjectName
|
||||
namespace: $namespace
|
||||
) @client {
|
||||
lastTimestamp
|
||||
message
|
||||
reason
|
||||
source
|
||||
type
|
||||
}
|
||||
}
|
||||
|
|
@ -165,5 +165,25 @@ export const kubernetesQueries = {
|
|||
}
|
||||
});
|
||||
},
|
||||
k8sEvents(_, { configuration, involvedObjectName, namespace }) {
|
||||
const fieldSelector = `involvedObject.name=${involvedObjectName}`;
|
||||
const config = new Configuration(configuration);
|
||||
|
||||
const coreV1Api = new CoreV1Api(config);
|
||||
const eventsApi = coreV1Api.listCoreV1NamespacedEvent({ namespace, fieldSelector });
|
||||
return eventsApi
|
||||
.then((res) => {
|
||||
const data = res?.items || [];
|
||||
|
||||
return data;
|
||||
})
|
||||
.catch(async (err) => {
|
||||
try {
|
||||
await handleClusterError(err);
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
k8sLogs,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -118,6 +118,14 @@ type K8sLogsData {
|
|||
error: JSON
|
||||
}
|
||||
|
||||
type K8sEvent {
|
||||
lastTimestamp: String
|
||||
message: String
|
||||
reason: String
|
||||
source: JSON
|
||||
type: String
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
environmentApp(page: Int, scope: String): LocalEnvironmentApp
|
||||
folder(environment: NestedLocalEnvironmentInput): LocalEnvironmentFolder
|
||||
|
|
@ -137,6 +145,11 @@ extend type Query {
|
|||
fluxHelmRelease(configuration: LocalConfiguration, fluxResourcePath: String): LocalFluxHelmRelease
|
||||
k8sDeployments(configuration: LocalConfiguration, namespace: String): [LocalK8sDeployment]
|
||||
k8sLogs(configuration: LocalConfiguration, namespace: String, podName: String): [K8sLogsData]
|
||||
k8sEvents(
|
||||
configuration: LocalConfiguration
|
||||
namespace: String
|
||||
involvedObjectName: String
|
||||
): [K8sEvent]
|
||||
}
|
||||
|
||||
input ResourceTypeParam {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div ref="milestoneDetails" class="issue-milestone-details">
|
||||
<gl-icon :size="16" class="flex-shrink-0 gl-mr-2" name="milestone" />
|
||||
<div ref="milestoneDetails" class="issue-milestone-details gl-flex gl-max-w-15 gl-gap-2">
|
||||
<gl-icon :size="16" class="flex-shrink-0" name="milestone" />
|
||||
<span class="milestone-title gl-inline-block gl-truncate">{{ milestone.title }}</span>
|
||||
<gl-tooltip :target="() => $refs.milestoneDetails" placement="bottom" class="js-item-milestone">
|
||||
<span class="gl-font-bold">{{ __('Milestone') }}</span> <br />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
<script>
|
||||
import { GlIcon, GlBadge, GlSprintf, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
|
||||
import {
|
||||
differenceInMilliseconds,
|
||||
stringifyTime,
|
||||
parseSeconds,
|
||||
localeDateFormat,
|
||||
} from '~/lib/utils/datetime_utility';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
source: s__('KubernetesDashboard|Source: %{source}'),
|
||||
justNow: s__('Timeago|just now'),
|
||||
},
|
||||
components: {
|
||||
GlIcon,
|
||||
GlBadge,
|
||||
GlSprintf,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip,
|
||||
},
|
||||
props: {
|
||||
event: {
|
||||
type: Object,
|
||||
required: true,
|
||||
validator: (item) =>
|
||||
['lastTimestamp', 'message', 'reason', 'source', 'type'].every((key) => item[key]),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
timeAgo() {
|
||||
const milliseconds = differenceInMilliseconds(new Date(this.event.lastTimestamp));
|
||||
const seconds = parseSeconds(milliseconds / 1000);
|
||||
|
||||
const timeAgo = stringifyTime(seconds);
|
||||
return timeAgo === '0m' ? this.$options.i18n.justNow : stringifyTime(seconds);
|
||||
},
|
||||
tooltipText() {
|
||||
return localeDateFormat.asDateTimeFull.format(this.event.lastTimestamp);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li class="timeline-entry">
|
||||
<div
|
||||
class="gl-float-left gl-ml-4 gl-mt-3 gl-h-3 gl-w-3 gl-rounded-full gl-border-1 gl-border-solid gl-border-gray-10 gl-bg-gray-100"
|
||||
></div>
|
||||
<div class="gl-pl-7 gl-pr-4">
|
||||
<header class="gl-mb-4 gl-flex gl-flex-wrap gl-items-center gl-gap-3">
|
||||
<gl-badge> {{ event.type }} </gl-badge>
|
||||
<gl-sprintf :message="$options.i18n.source">
|
||||
<template #source>
|
||||
<span>{{ event.source.component }}</span>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
<span v-gl-tooltip :title="tooltipText" data-testid="event-last-timestamp">
|
||||
<gl-icon name="calendar" />
|
||||
<time :time="event.lastTimestamp">
|
||||
{{ timeAgo }}
|
||||
</time>
|
||||
</span>
|
||||
</header>
|
||||
<p class="gl-mb-6 gl-break-words">
|
||||
<strong>{{ event.reason }}: </strong>{{ event.message }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
|
@ -1,29 +1,77 @@
|
|||
<script>
|
||||
import { GlBadge, GlTruncate, GlButton, GlTooltipDirective } from '@gitlab/ui';
|
||||
import {
|
||||
GlBadge,
|
||||
GlTruncate,
|
||||
GlButton,
|
||||
GlTooltipDirective,
|
||||
GlLoadingIcon,
|
||||
GlAlert,
|
||||
} from '@gitlab/ui';
|
||||
import { stringify } from 'yaml';
|
||||
import { s__ } from '~/locale';
|
||||
import PodLogsButton from '~/environments/environment_details/components/kubernetes/pod_logs_button.vue';
|
||||
import getK8sEventsQuery from '~/environments/graphql/queries/k8s_events.query.graphql';
|
||||
import { WORKLOAD_STATUS_BADGE_VARIANTS, STATUS_LABELS } from '../constants';
|
||||
import WorkloadDetailsItem from './workload_details_item.vue';
|
||||
import K8sEventItem from './k8s_event_item.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlBadge,
|
||||
GlTruncate,
|
||||
GlButton,
|
||||
GlLoadingIcon,
|
||||
GlAlert,
|
||||
WorkloadDetailsItem,
|
||||
PodLogsButton,
|
||||
K8sEventItem,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
props: {
|
||||
configuration: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
validator: (item) => ['name', 'kind', 'labels', 'annotations'].every((key) => item[key]),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return { eventsError: null, eventsLoading: false, k8sEvents: [] };
|
||||
},
|
||||
apollo: {
|
||||
k8sEvents: {
|
||||
query: getK8sEventsQuery,
|
||||
fetchPolicy: 'no-cache',
|
||||
notifyOnNetworkStatusChange: true,
|
||||
variables() {
|
||||
return {
|
||||
configuration: this.configuration,
|
||||
involvedObjectName: this.item.name,
|
||||
namespace: this.item.namespace,
|
||||
};
|
||||
},
|
||||
skip() {
|
||||
return Boolean(!Object.keys(this.configuration).length);
|
||||
},
|
||||
error(err) {
|
||||
this.eventsError = err.message;
|
||||
},
|
||||
watchLoading(isLoading) {
|
||||
this.eventsLoading = isLoading;
|
||||
},
|
||||
update(data) {
|
||||
return data?.k8sEvents?.sort(
|
||||
(a, b) => new Date(b.lastTimestamp) - new Date(a.lastTimestamp),
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
itemLabels() {
|
||||
const { labels } = this.item;
|
||||
|
|
@ -79,6 +127,8 @@ export default {
|
|||
annotations: s__('KubernetesDashboard|Annotations'),
|
||||
spec: s__('KubernetesDashboard|Spec'),
|
||||
containers: s__('KubernetesDashboard|Containers'),
|
||||
events: s__('KubernetesDashboard|Events'),
|
||||
eventsEmptyText: s__('KubernetesDashboard|No events available'),
|
||||
},
|
||||
WORKLOAD_STATUS_BADGE_VARIANTS,
|
||||
STATUS_LABELS,
|
||||
|
|
@ -155,5 +205,17 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
</workload-details-item>
|
||||
<workload-details-item :label="$options.i18n.events" collapsible>
|
||||
<gl-loading-icon v-if="eventsLoading" inline />
|
||||
<gl-alert v-else-if="eventsError" variant="danger" :dismissible="false">
|
||||
{{ eventsError }}
|
||||
</gl-alert>
|
||||
<div v-else-if="k8sEvents.length" class="issuable-discussion">
|
||||
<ul class="notes main-notes-list timeline -gl-ml-2">
|
||||
<k8s-event-item v-for="(event, index) in k8sEvents" :key="index" :event="event" />
|
||||
</ul>
|
||||
</div>
|
||||
<span v-else class="gl-text-gray-500">{{ $options.i18n.eventsEmptyText }}</span>
|
||||
</workload-details-item>
|
||||
</ul>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="gl-flex gl-justify-between">
|
||||
<div class="gl-flex gl-flex-wrap gl-items-center gl-gap-2">
|
||||
<span class="gl-text-sm gl-text-secondary">{{ reference }}</span>
|
||||
<div class="gl-flex gl-flex-wrap gl-items-center gl-gap-3 gl-text-sm gl-text-secondary">
|
||||
<span>{{ reference }}</span>
|
||||
<item-milestone
|
||||
v-if="milestone"
|
||||
:milestone="milestone"
|
||||
class="gl-flex gl-max-w-15 !gl-cursor-help gl-items-center gl-text-sm gl-leading-normal !gl-text-gray-900 !gl-no-underline"
|
||||
class="gl-flex gl-max-w-15 !gl-cursor-help gl-items-center gl-gap-2 gl-leading-normal !gl-no-underline"
|
||||
/>
|
||||
<slot name="left-metadata"></slot>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ module Groups::GroupMembersHelper
|
|||
|
||||
def group_group_links_list_data(group, include_relations, search)
|
||||
group_links = group_group_links(group, include_relations)
|
||||
group_links = group_links.search(search) if search
|
||||
group_links = group_links.search(search, include_parents: true) if search
|
||||
|
||||
{
|
||||
members: group_group_links_serialized(group, group_links),
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ module Projects::ProjectMembersHelper
|
|||
|
||||
if include_relations.include?(:inherited)
|
||||
group_group_links = project.group_group_links.distinct_on_shared_with_group_id_with_group_access
|
||||
group_group_links = group_group_links.search(search) if search
|
||||
group_group_links = group_group_links.search(search, include_parents: true) if search
|
||||
members += group_group_links_serialized(project, group_group_links)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ class GroupGroupLink < ApplicationRecord
|
|||
|
||||
alias_method :shared_from, :shared_group
|
||||
|
||||
def self.search(query)
|
||||
joins(:shared_with_group).merge(Group.search(query))
|
||||
def self.search(query, **options)
|
||||
joins(:shared_with_group).merge(Group.search(query, **options))
|
||||
end
|
||||
|
||||
def self.access_options
|
||||
|
|
|
|||
|
|
@ -2539,6 +2539,8 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def should_delay_delete?(deleted_by)
|
||||
return false if placeholder?
|
||||
|
||||
is_deleting_own_record = deleted_by.id == id
|
||||
|
||||
is_deleting_own_record &&
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ module Users
|
|||
|
||||
# Asynchronously destroys +user+
|
||||
# Migrating the associated user records, and post-migration cleanup is
|
||||
# handled by the Users::MigrateRecordsToGhostUserWorker cron worker.
|
||||
# handled by the Users::MigrateRecordsToGhostUserInBatchesWorker cron worker.
|
||||
#
|
||||
# The operation will fail if the user is the sole owner of any groups. To
|
||||
# force the groups to be destroyed, pass `delete_solo_owned_groups: true` in
|
||||
|
|
@ -71,12 +71,7 @@ module Users
|
|||
|
||||
yield(user) if block_given?
|
||||
|
||||
hard_delete = options.fetch(:hard_delete, false)
|
||||
Users::GhostUserMigration.create!(
|
||||
user: user,
|
||||
initiator_user: current_user,
|
||||
hard_delete: hard_delete
|
||||
)
|
||||
create_ghost_user(user, options)
|
||||
|
||||
update_metrics
|
||||
end
|
||||
|
|
@ -85,6 +80,17 @@ module Users
|
|||
|
||||
attr_reader :scheduled_records_gauge, :lag_gauge
|
||||
|
||||
def create_ghost_user(user, options)
|
||||
hard_delete = options.fetch(:hard_delete, false)
|
||||
Users::GhostUserMigration.create!(
|
||||
user: user,
|
||||
initiator_user: current_user,
|
||||
hard_delete: hard_delete
|
||||
)
|
||||
rescue ActiveRecord::RecordNotUnique
|
||||
# GhostUserMigration was already created by other worker process. Do nothing
|
||||
end
|
||||
|
||||
def update_metrics
|
||||
update_scheduled_records_gauge
|
||||
update_lag_gauge
|
||||
|
|
|
|||
|
|
@ -3279,6 +3279,15 @@
|
|||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: import_delete_placeholder_user
|
||||
:worker_name: Import::DeletePlaceholderUserWorker
|
||||
:feature_category: :importers
|
||||
:has_external_dependencies: false
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: import_issues_csv
|
||||
:worker_name: ImportIssuesCsvWorker
|
||||
:feature_category: :team_planning
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Import
|
||||
class DeletePlaceholderUserWorker
|
||||
include ApplicationWorker
|
||||
|
||||
data_consistency :delayed
|
||||
idempotent!
|
||||
feature_category :importers
|
||||
|
||||
def perform(source_user_id)
|
||||
source_user = Import::SourceUser.find_by_id(source_user_id)
|
||||
return if source_user.nil? || source_user.placeholder_user.nil?
|
||||
return unless source_user.placeholder_user.placeholder?
|
||||
|
||||
if placeholder_user_referenced?(source_user)
|
||||
log_placeholder_user_not_deleted(source_user)
|
||||
return
|
||||
end
|
||||
|
||||
placeholder_user = source_user.placeholder_user
|
||||
|
||||
placeholder_user.delete_async(
|
||||
deleted_by: placeholder_user,
|
||||
params: { "skip_authorization" => true }
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_placeholder_user_not_deleted(source_user)
|
||||
::Import::Framework::Logger.warn(
|
||||
message: 'Unable to delete placeholder user because it is still referenced in other tables',
|
||||
source_user_id: source_user.id
|
||||
)
|
||||
end
|
||||
|
||||
def placeholder_user_referenced?(source_user)
|
||||
PlaceholderReferences::AliasResolver.models_with_columns.any? do |model, columns|
|
||||
(columns & ::Gitlab::ImportExport::Base::RelationFactory::USER_REFERENCES).any? do |user_reference_column|
|
||||
model.where(user_reference_column => source_user.placeholder_user_id).any? # rubocop:disable CodeReuse/ActiveRecord -- Adding a scope for all possible models would not be feasible here
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -27,6 +27,7 @@ module Import
|
|||
return unless import_source_user_valid?
|
||||
|
||||
Import::ReassignPlaceholderUserRecordsService.new(import_source_user).execute
|
||||
Import::DeletePlaceholderUserWorker.perform_async(import_source_user.id)
|
||||
end
|
||||
|
||||
def perform_failure(exception, import_source_user_id)
|
||||
|
|
|
|||
|
|
@ -411,6 +411,8 @@
|
|||
- 1
|
||||
- - groups_update_two_factor_requirement_for_members
|
||||
- 1
|
||||
- - import_delete_placeholder_user
|
||||
- 1
|
||||
- - import_issues_csv
|
||||
- 2
|
||||
- - import_load_placeholder_references
|
||||
|
|
|
|||
|
|
@ -302,9 +302,26 @@ module.exports = {
|
|||
rules: [
|
||||
{
|
||||
type: 'javascript/auto',
|
||||
exclude: /pdfjs-dist/,
|
||||
test: /\.mjs$/,
|
||||
use: [],
|
||||
},
|
||||
{
|
||||
test: /(pdfjs).*\.js?$/,
|
||||
include: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: [
|
||||
'@babel/plugin-transform-optional-chaining',
|
||||
'@babel/plugin-transform-logical-assignment-operators',
|
||||
],
|
||||
...defaultJsOptions,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /(@gitlab\/web-ide).*\.js?$/,
|
||||
include: /node_modules/,
|
||||
|
|
|
|||
|
|
@ -5427,6 +5427,29 @@ Input type: `GroupMemberBulkUpdateInput`
|
|||
| <a id="mutationgroupmemberbulkupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationgroupmemberbulkupdategroupmembers"></a>`groupMembers` | [`[GroupMember!]`](#groupmember) | Group members after mutation. |
|
||||
|
||||
### `Mutation.groupMembersExport`
|
||||
|
||||
DETAILS:
|
||||
**Introduced** in GitLab 17.4.
|
||||
**Status**: Experiment.
|
||||
|
||||
Input type: `GroupMembersExportInput`
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationgroupmembersexportclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationgroupmembersexportgroupid"></a>`groupId` | [`GroupID!`](#groupid) | Global ID of the group. |
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mutationgroupmembersexportclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
|
||||
| <a id="mutationgroupmembersexporterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
|
||||
| <a id="mutationgroupmembersexportmessage"></a>`message` | [`String`](#string) | Export request result message. |
|
||||
|
||||
### `Mutation.groupSavedReplyCreate`
|
||||
|
||||
DETAILS:
|
||||
|
|
|
|||
|
|
@ -151,6 +151,12 @@ module Import
|
|||
column
|
||||
end
|
||||
|
||||
def self.models_with_columns
|
||||
ALIASES.values
|
||||
.map { |versions| versions[versions.keys.max] }
|
||||
.map { |data| [data[:model], data[:columns].values] }
|
||||
end
|
||||
|
||||
private_class_method def self.track_error_for_missing(model:, column: nil, version: nil)
|
||||
message = "ALIASES must be extended to include #{model}"
|
||||
message += ".#{column}" if column
|
||||
|
|
|
|||
|
|
@ -31158,6 +31158,9 @@ msgstr ""
|
|||
msgid "KubernetesDashboard|Deployments"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|Events"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|Failed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -31191,6 +31194,9 @@ msgstr ""
|
|||
msgid "KubernetesDashboard|No agent selected"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|No events available"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|Pending"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -31218,6 +31224,9 @@ msgstr ""
|
|||
msgid "KubernetesDashboard|Services"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|Source: %{source}"
|
||||
msgstr ""
|
||||
|
||||
msgid "KubernetesDashboard|Spec"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@
|
|||
"orderedmap": "^2.1.1",
|
||||
"papaparse": "^5.3.1",
|
||||
"patch-package": "6.5.1",
|
||||
"pdfjs-dist": "^2.16.105",
|
||||
"pdfjs-dist": "^3.11.174",
|
||||
"pikaday": "^1.8.0",
|
||||
"pinia": "^2.2.2",
|
||||
"popper.js": "^1.16.1",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :issue_assignee do
|
||||
assignee { association(:user) }
|
||||
issue { association(:issue) }
|
||||
end
|
||||
end
|
||||
|
|
@ -339,6 +339,10 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_ov
|
|||
expect(findWorkloadDetails().props('item')).toEqual(mockPodsTableItems[0]);
|
||||
});
|
||||
|
||||
it('provides the agent access configuration to the drawer', () => {
|
||||
expect(findWorkloadDetails().props('configuration')).toEqual(configuration);
|
||||
});
|
||||
|
||||
it('renders a title with the selected item name', () => {
|
||||
expect(findDrawer().text()).toContain(mockPodsTableItems[0].name);
|
||||
});
|
||||
|
|
@ -383,6 +387,7 @@ describe('~/environments/environment_details/components/kubernetes/kubernetes_ov
|
|||
it('provides the resource details to the drawer', () => {
|
||||
const selectedItem = {
|
||||
name: fluxKustomization.metadata.name,
|
||||
namespace: fluxKustomization.metadata.namespace,
|
||||
status: 'reconciled',
|
||||
labels: fluxKustomization.metadata.labels,
|
||||
annotations: fluxKustomization.metadata.annotations,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import {
|
|||
k8sPodsMock,
|
||||
k8sServicesMock,
|
||||
k8sDeploymentsMock,
|
||||
k8sEventsMock,
|
||||
} from 'jest/kubernetes_dashboard/graphql/mock_data';
|
||||
import { k8sNamespacesMock } from '../mock_data';
|
||||
import { bootstrapWatcherMock } from '../watcher_mock_helper';
|
||||
|
|
@ -373,6 +374,45 @@ describe('~/frontend/environments/graphql/resolvers', () => {
|
|||
);
|
||||
});
|
||||
|
||||
describe('k8sEvents', () => {
|
||||
const involvedObjectName = 'my-pod';
|
||||
const mockEventsListFn = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
items: k8sEventsMock,
|
||||
});
|
||||
});
|
||||
|
||||
const mockNamespacedEventsListFn = jest.fn().mockImplementation(mockEventsListFn);
|
||||
|
||||
it('should request namespaced events with the field selector from the cluster_client library if namespace is specified', async () => {
|
||||
jest
|
||||
.spyOn(CoreV1Api.prototype, 'listCoreV1NamespacedEvent')
|
||||
.mockImplementation(mockNamespacedEventsListFn);
|
||||
|
||||
const events = await mockResolvers.Query.k8sEvents(null, {
|
||||
configuration,
|
||||
namespace,
|
||||
involvedObjectName,
|
||||
});
|
||||
|
||||
expect(mockNamespacedEventsListFn).toHaveBeenCalledWith({
|
||||
namespace,
|
||||
fieldSelector: `involvedObject.name=${involvedObjectName}`,
|
||||
});
|
||||
expect(events).toEqual(k8sEventsMock);
|
||||
});
|
||||
|
||||
it('should throw an error if the API call fails', async () => {
|
||||
jest
|
||||
.spyOn(CoreV1Api.prototype, 'listCoreV1NamespacedEvent')
|
||||
.mockRejectedValue(new Error('API error'));
|
||||
|
||||
await expect(
|
||||
mockResolvers.Query.k8sEvents(null, { configuration, namespace, involvedObjectName }),
|
||||
).rejects.toThrow('API error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteKubernetesPod', () => {
|
||||
const mockPodsDeleteFn = jest.fn().mockResolvedValue({ errors: [] });
|
||||
const podToDelete = 'my-pod';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlBadge, GlSprintf } from '@gitlab/ui';
|
||||
import K8sEventItem from '~/kubernetes_dashboard/components/k8s_event_item.vue';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
|
||||
describe('~/kubernetes_dashboard/components/k8s_event_item.vue', () => {
|
||||
useFakeDate(2023, 4, 1, 12, 4);
|
||||
let wrapper;
|
||||
|
||||
const event = {
|
||||
type: 'normal',
|
||||
source: { component: 'my-component' },
|
||||
reason: 'Reason 1',
|
||||
message: 'Event 1',
|
||||
lastTimestamp: '2023-05-01T12:00:00Z',
|
||||
};
|
||||
|
||||
const findTypeBadge = () => wrapper.findComponent(GlBadge);
|
||||
const findLastTimestamp = () => wrapper.find('[data-testid="event-last-timestamp"]');
|
||||
|
||||
const createWrapper = () => {
|
||||
wrapper = shallowMount(K8sEventItem, {
|
||||
propsData: {
|
||||
event,
|
||||
},
|
||||
stubs: { GlSprintf },
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createWrapper();
|
||||
});
|
||||
|
||||
it('renders type badge', () => {
|
||||
expect(findTypeBadge().text()).toBe(event.type);
|
||||
});
|
||||
|
||||
it('renders event source', () => {
|
||||
expect(wrapper.text()).toContain(`Source: ${event.source.component}`);
|
||||
});
|
||||
|
||||
it('renders event last timestamp tooltip in correct format', () => {
|
||||
expect(findLastTimestamp().attributes('title')).toBe('May 1, 2023 at 12:00:00 PM GMT');
|
||||
});
|
||||
|
||||
it('renders event age as text', () => {
|
||||
expect(findLastTimestamp().text()).toBe('4m');
|
||||
});
|
||||
|
||||
it('renders event reason with message', () => {
|
||||
expect(wrapper.text()).toContain(`${event.reason}: ${event.message}`);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,14 +1,28 @@
|
|||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlBadge, GlTruncate, GlButton } from '@gitlab/ui';
|
||||
import { GlBadge, GlTruncate, GlButton, GlLoadingIcon, GlAlert } from '@gitlab/ui';
|
||||
import WorkloadDetails from '~/kubernetes_dashboard/components/workload_details.vue';
|
||||
import WorkloadDetailsItem from '~/kubernetes_dashboard/components/workload_details_item.vue';
|
||||
import { WORKLOAD_STATUS_BADGE_VARIANTS } from '~/kubernetes_dashboard/constants';
|
||||
import PodLogsButton from '~/environments/environment_details/components/kubernetes/pod_logs_button.vue';
|
||||
import { mockPodsTableItems } from '../graphql/mock_data';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import K8sEventItem from '~/kubernetes_dashboard/components/k8s_event_item.vue';
|
||||
import { mockPodsTableItems, k8sEventsMock } from '../graphql/mock_data';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
let wrapper;
|
||||
let getK8sEventsQuery;
|
||||
|
||||
const defaultItem = mockPodsTableItems[2];
|
||||
const configuration = {
|
||||
basePath: 'kas/tunnel/url',
|
||||
baseOptions: {
|
||||
headers: { 'GitLab-Agent-Id': '1' },
|
||||
},
|
||||
};
|
||||
|
||||
const createWrapper = (item = defaultItem) => {
|
||||
wrapper = shallowMount(WorkloadDetails, {
|
||||
|
|
@ -19,6 +33,26 @@ const createWrapper = (item = defaultItem) => {
|
|||
});
|
||||
};
|
||||
|
||||
const createApolloProvider = () => {
|
||||
const mockResolvers = {
|
||||
Query: {
|
||||
k8sEvents: getK8sEventsQuery,
|
||||
},
|
||||
};
|
||||
|
||||
return createMockApollo([], mockResolvers);
|
||||
};
|
||||
|
||||
const createWrapperWithApollo = () => {
|
||||
wrapper = shallowMount(WorkloadDetails, {
|
||||
propsData: {
|
||||
item: defaultItem,
|
||||
configuration,
|
||||
},
|
||||
apolloProvider: createApolloProvider(),
|
||||
});
|
||||
};
|
||||
|
||||
const findAllWorkloadDetailsItems = () => wrapper.findAllComponents(WorkloadDetailsItem);
|
||||
const findWorkloadDetailsItem = (at) => findAllWorkloadDetailsItems().at(at);
|
||||
const findAllBadges = () => wrapper.findAllComponents(GlBadge);
|
||||
|
|
@ -27,6 +61,9 @@ const findAllPodLogsButtons = () => wrapper.findAllComponents(PodLogsButton);
|
|||
const findPodLogsButton = (at) => findAllPodLogsButtons().at(at);
|
||||
const findAllButtons = () => wrapper.findAllComponents(GlButton);
|
||||
const findButton = (at) => findAllButtons().at(at);
|
||||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findAllK8sEventItems = () => wrapper.findAllComponents(K8sEventItem);
|
||||
|
||||
describe('Workload details component', () => {
|
||||
describe('when minimal fields are provided', () => {
|
||||
|
|
@ -156,5 +193,70 @@ describe('Workload details component', () => {
|
|||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('k8s events', () => {
|
||||
describe('default', () => {
|
||||
beforeEach(() => {
|
||||
getK8sEventsQuery = jest.fn().mockResolvedValue([]);
|
||||
createWrapperWithApollo();
|
||||
});
|
||||
it('renders a collapsible list item for events', () => {
|
||||
expect(findWorkloadDetailsItem(6).props('label')).toBe('Events');
|
||||
});
|
||||
|
||||
it('requests k8s events for the current item', async () => {
|
||||
getK8sEventsQuery = jest.fn().mockResolvedValue([]);
|
||||
createWrapperWithApollo();
|
||||
await nextTick();
|
||||
|
||||
expect(getK8sEventsQuery).toHaveBeenCalledWith(
|
||||
{},
|
||||
expect.objectContaining({
|
||||
configuration,
|
||||
namespace: defaultItem.namespace,
|
||||
involvedObjectName: defaultItem.name,
|
||||
}),
|
||||
expect.any(Object),
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
|
||||
it('renders loading icon while loading events', async () => {
|
||||
getK8sEventsQuery = jest.fn().mockResolvedValue([]);
|
||||
createWrapperWithApollo();
|
||||
await nextTick();
|
||||
|
||||
expect(findLoadingIcon().exists()).toBe(true);
|
||||
await waitForPromises();
|
||||
|
||||
expect(findLoadingIcon().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('shows empty state message when no events are found', async () => {
|
||||
getK8sEventsQuery = jest.fn().mockResolvedValue([]);
|
||||
createWrapperWithApollo();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findWorkloadDetailsItem(6).text()).toBe('No events available');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders error alert when the request errored', async () => {
|
||||
const error = new Error('Error from the cluster_client API');
|
||||
getK8sEventsQuery = jest.fn().mockRejectedValue(error);
|
||||
createWrapperWithApollo();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findAlert().text()).toBe(error.message);
|
||||
});
|
||||
|
||||
it("renders a list of k8s-event-item's for each event", async () => {
|
||||
getK8sEventsQuery = jest.fn().mockResolvedValue(k8sEventsMock);
|
||||
createWrapperWithApollo();
|
||||
await waitForPromises();
|
||||
|
||||
expect(findAllK8sEventItems()).toHaveLength(k8sEventsMock.length);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -635,3 +635,27 @@ export const mockServicesTableItems = [
|
|||
kind: 'Service',
|
||||
},
|
||||
];
|
||||
|
||||
export const k8sEventsMock = [
|
||||
{
|
||||
type: 'normal',
|
||||
source: { component: 'my-component' },
|
||||
reason: 'Reason 1',
|
||||
message: 'Event 1',
|
||||
lastTimestamp: '2023-05-01T10:00:00Z',
|
||||
},
|
||||
{
|
||||
type: 'normal',
|
||||
source: { component: 'my-component' },
|
||||
reason: 'Reason 2',
|
||||
message: 'Event 2',
|
||||
lastTimestamp: '2023-05-01T11:00:00Z',
|
||||
},
|
||||
{
|
||||
type: 'normal',
|
||||
source: { component: 'my-component' },
|
||||
reason: 'Reason 3',
|
||||
message: 'Event 3',
|
||||
lastTimestamp: '2023-05-01T12:00:00Z',
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Groups::GroupMembersHelper do
|
||||
RSpec.describe Groups::GroupMembersHelper, feature_category: :groups_and_projects do
|
||||
include MembersPresentation
|
||||
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::ProjectMembersHelper do
|
||||
RSpec.describe Projects::ProjectMembersHelper, feature_category: :groups_and_projects do
|
||||
include MembersPresentation
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -204,4 +204,38 @@ RSpec.describe Import::PlaceholderReferences::AliasResolver, feature_category: :
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".models_with_columns" do
|
||||
subject(:models_with_columns) { described_class.models_with_columns }
|
||||
|
||||
it "returns models with all their columns" do
|
||||
expect(models_with_columns).to include([Approval, ["user_id"]])
|
||||
end
|
||||
|
||||
context "when there are multiple versions for a key" do
|
||||
let(:aliases) do
|
||||
{
|
||||
"Note" => {
|
||||
1 => {
|
||||
model: Note,
|
||||
columns: { "author_id" => "author_id" }
|
||||
},
|
||||
2 => {
|
||||
model: Note,
|
||||
columns: { "author_id" => "user_id" }
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
stub_const("#{described_class}::ALIASES", aliases)
|
||||
end
|
||||
|
||||
it "only includes the last version" do
|
||||
expect(models_with_columns).to include([Note, ["user_id"]])
|
||||
expect(models_with_columns).not_to include([Note, ["author_id"]])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GroupGroupLink do
|
||||
RSpec.describe GroupGroupLink, feature_category: :groups_and_projects do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:nested_group) { create(:group, parent: group) }
|
||||
let_it_be(:shared_group) { create(:group) }
|
||||
|
||||
describe 'validation' do
|
||||
|
|
@ -185,4 +186,18 @@ RSpec.describe GroupGroupLink do
|
|||
it { expect(described_class.search(group.name)).to eq([group_group_link]) }
|
||||
it { expect(described_class.search('not-a-group-name')).to be_empty }
|
||||
end
|
||||
|
||||
describe 'search by parent group name without `include_parents` option' do
|
||||
let_it_be(:group_group_link) { create(:group_group_link, :reporter, shared_with_group: nested_group) }
|
||||
|
||||
it { expect(described_class.search(group.name)).to be_empty }
|
||||
it { expect(described_class.search('not-a-group-name')).to be_empty }
|
||||
end
|
||||
|
||||
describe 'search by parent group name with `include_parents` option' do
|
||||
let_it_be(:group_group_link) { create(:group_group_link, :reporter, shared_with_group: nested_group) }
|
||||
|
||||
it { expect(described_class.search(group.name, include_parents: true)).to eq([group_group_link]) }
|
||||
it { expect(described_class.search('not-a-group-name')).to be_empty }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6549,13 +6549,19 @@ RSpec.describe User, feature_category: :user_profile do
|
|||
|
||||
context 'with possible spam contribution' do
|
||||
context 'with comments' do
|
||||
it_behaves_like 'schedules the record for deletion with the correct delay' do
|
||||
before do
|
||||
allow(user).to receive(:has_possible_spam_contributions?).and_call_original
|
||||
before do
|
||||
allow(user).to receive(:has_possible_spam_contributions?).and_call_original
|
||||
|
||||
note = create(:note_on_issue, author: user)
|
||||
create(:event, :commented, target: note, author: user)
|
||||
end
|
||||
note = create(:note_on_issue, author: user)
|
||||
create(:event, :commented, target: note, author: user)
|
||||
end
|
||||
|
||||
it_behaves_like 'schedules the record for deletion with the correct delay'
|
||||
|
||||
context 'when user is a placeholder' do
|
||||
let(:user) { create(:user, :placeholder, note: "existing note") }
|
||||
|
||||
it_behaves_like 'schedules user for deletion without delay'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar
|
|||
mr = MergeRequest.find(merge_request.id)
|
||||
|
||||
threads << Thread.new do
|
||||
described_class.new(mr).execute(retry_lease: retry_lease)
|
||||
Gitlab::ExclusiveLease.skipping_transaction_check do
|
||||
described_class.new(mr).execute(retry_lease: retry_lease)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -225,6 +225,19 @@ RSpec.describe Users::DestroyService, feature_category: :user_management do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when running the service twice for a user with no personal projects' do
|
||||
let!(:project) { nil }
|
||||
|
||||
it 'does not create a second ghost user migration and does not raise an exception' do
|
||||
expect { described_class.new(user).execute(user) }
|
||||
.to change { Users::GhostUserMigration.where(user: user).count }.by(1)
|
||||
|
||||
expect do
|
||||
expect { described_class.new(user).execute(user) }.not_to raise_exception
|
||||
end.not_to change { Users::GhostUserMigration.where(user: user).count }
|
||||
end
|
||||
end
|
||||
|
||||
it 'allows users to delete their own account' do
|
||||
expect { described_class.new(user).execute(user) }
|
||||
.to(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Import::DeletePlaceholderUserWorker, feature_category: :importers do
|
||||
let_it_be(:placeholder_user) { create(:user, :placeholder) }
|
||||
let_it_be(:source_user) { create(:import_source_user, placeholder_user: placeholder_user) }
|
||||
|
||||
let(:job_args) { source_user.id }
|
||||
|
||||
subject(:perform) { described_class.new.perform(*job_args) }
|
||||
|
||||
it_behaves_like 'an idempotent worker'
|
||||
|
||||
shared_examples 'deletes the placeholder user' do
|
||||
it 'deletes the placeholder_user' do
|
||||
expect(DeleteUserWorker).to receive(:perform_async).with(
|
||||
placeholder_user.id, placeholder_user.id, { "skip_authorization" => true }
|
||||
)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'does not delete the placeholder_user and logs the issue' do
|
||||
it 'does not delete the placeholder_user and logs the issue' do
|
||||
expect(::Import::Framework::Logger).to receive(:warn).with(
|
||||
message: 'Unable to delete placeholder user because it is still referenced in other tables',
|
||||
source_user_id: source_user.id
|
||||
)
|
||||
|
||||
expect(DeleteUserWorker).not_to receive(:perform_async)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no tables reference the user' do
|
||||
it_behaves_like 'deletes the placeholder user'
|
||||
end
|
||||
|
||||
context 'when another table references the user from an author_id column' do
|
||||
let!(:note) { create(:note, author: placeholder_user) }
|
||||
|
||||
it_behaves_like 'does not delete the placeholder_user and logs the issue'
|
||||
end
|
||||
|
||||
context 'when another table references the user from a user_id column' do
|
||||
let!(:approval) { create(:approval, user: placeholder_user) }
|
||||
|
||||
it_behaves_like 'does not delete the placeholder_user and logs the issue'
|
||||
end
|
||||
|
||||
context 'when an issue_id happens to equal the placeholder user ID' do
|
||||
let!(:issue_assignee) { create(:issue_assignee, issue_id: issue.id) }
|
||||
|
||||
let!(:issue) do
|
||||
Issue.find_by_id(placeholder_user.id) || create(:issue, id: placeholder_user.id)
|
||||
end
|
||||
|
||||
it_behaves_like 'deletes the placeholder user'
|
||||
end
|
||||
|
||||
context 'when there is no placeholder user' do
|
||||
let_it_be(:source_user) { create(:import_source_user, :completed, placeholder_user: nil) }
|
||||
|
||||
it 'does not delete the placeholder_user and does not log an issue' do
|
||||
expect(::Import::Framework::Logger).not_to receive(:warn)
|
||||
expect(DeleteUserWorker).not_to receive(:perform_async)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'when attempting to delete a user who is not a placeholder' do
|
||||
let_it_be(:user) { create(:user, :import_user) }
|
||||
let_it_be(:source_user) { create(:import_source_user, placeholder_user: user) }
|
||||
|
||||
it 'does not delete the user' do
|
||||
expect(DeleteUserWorker).not_to receive(:perform_async)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -62,6 +62,13 @@ RSpec.describe Import::ReassignPlaceholderUserRecordsWorker, feature_category: :
|
|||
perform_multiple(job_args)
|
||||
end
|
||||
end
|
||||
|
||||
it 'queues a DeletePlaceholderUserWorker with the source user ID' do
|
||||
expect(Import::DeletePlaceholderUserWorker)
|
||||
.to receive(:perform_async).with(import_source_user.id)
|
||||
|
||||
perform_multiple(job_args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
200
yarn.lock
200
yarn.lock
|
|
@ -1857,6 +1857,21 @@
|
|||
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz#0300943770e04231041a51bd39f0439b5c7ab4f0"
|
||||
integrity sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.0":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||
integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==
|
||||
dependencies:
|
||||
detect-libc "^2.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
make-dir "^3.1.0"
|
||||
node-fetch "^2.6.7"
|
||||
nopt "^5.0.0"
|
||||
npmlog "^5.0.1"
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.3.5"
|
||||
tar "^6.1.11"
|
||||
|
||||
"@mattiasbuelens/web-streams-adapter@^0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@mattiasbuelens/web-streams-adapter/-/web-streams-adapter-0.1.0.tgz#607b5a25682f4ae2741da7ba6df39302505336b3"
|
||||
|
|
@ -3838,11 +3853,19 @@ apollo3-cache-persist@^0.14.1:
|
|||
resolved "https://registry.yarnpkg.com/apollo3-cache-persist/-/apollo3-cache-persist-0.14.1.tgz#8f4c016b4d413aa28f68429b37c8d12524b5983b"
|
||||
integrity sha512-p/jNzN/MmSd0TmY7/ts0B3qi0SdQ3w9yNLQdKqB3GGb9xATUlAum2v4hSrTeWd/DZKK2Z7Xg5kFXTH6nNVnKSQ==
|
||||
|
||||
aproba@^1.1.1:
|
||||
"aproba@^1.0.3 || ^2.0.0", aproba@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||
|
||||
are-we-there-yet@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c"
|
||||
integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
arg@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
||||
|
|
@ -4586,6 +4609,15 @@ canvas-confetti@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/canvas-confetti/-/canvas-confetti-1.4.0.tgz#840f6db4a566f8f32abe28c00dcd82acf39c92bd"
|
||||
integrity sha512-S18o4Y9PqI/uabdlT/jI3MY7XBJjNxnfapFIkjkMwpz6qNxLFZOm2b22OMf4ZYDL9lpNWI+Ih4fEMVPwO1KHFQ==
|
||||
|
||||
canvas@^2.11.2:
|
||||
version "2.11.2"
|
||||
resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860"
|
||||
integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.0"
|
||||
nan "^2.17.0"
|
||||
simple-get "^3.0.3"
|
||||
|
||||
ccount@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
|
||||
|
|
@ -4783,6 +4815,11 @@ color-name@^1.1.4, color-name@~1.1.4:
|
|||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-support@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||
|
||||
colord@^2.9.3:
|
||||
version "2.9.3"
|
||||
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
|
||||
|
|
@ -4920,6 +4957,11 @@ console-browserify@^1.1.0:
|
|||
dependencies:
|
||||
date-now "^0.1.4"
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
|
||||
|
||||
consolidate@^0.15.1:
|
||||
version "0.15.1"
|
||||
resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
|
||||
|
|
@ -5880,6 +5922,13 @@ decode-uri-component@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9"
|
||||
integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==
|
||||
|
||||
decompress-response@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
|
||||
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
|
||||
dependencies:
|
||||
mimic-response "^2.0.0"
|
||||
|
||||
decompress-response@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||
|
|
@ -5980,6 +6029,11 @@ delegate@^3.1.2:
|
|||
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.1.2.tgz#1e1bc6f5cadda6cb6cbf7e6d05d0bcdd5712aebe"
|
||||
integrity sha1-HhvG9crdpstsv35tBdC83VcSrr4=
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
|
||||
|
||||
depd@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
|
||||
|
|
@ -6129,11 +6183,6 @@ domexception@^4.0.0:
|
|||
dependencies:
|
||||
webidl-conversions "^7.0.0"
|
||||
|
||||
dommatrix@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dommatrix/-/dommatrix-1.0.3.tgz#e7c18e8d6f3abdd1fef3dd4aa74c4d2e620a0525"
|
||||
integrity sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==
|
||||
|
||||
dompurify@^3.0.5, dompurify@^3.1.6:
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2"
|
||||
|
|
@ -7371,6 +7420,21 @@ fuzzaldrin-plus@^0.6.0:
|
|||
resolved "https://registry.yarnpkg.com/fuzzaldrin-plus/-/fuzzaldrin-plus-0.6.0.tgz#832f6489fbe876769459599c914a670ec22947ee"
|
||||
integrity sha1-gy9kifvodnaUWVmckUpnDsIpR+4=
|
||||
|
||||
gauge@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395"
|
||||
integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==
|
||||
dependencies:
|
||||
aproba "^1.0.3 || ^2.0.0"
|
||||
color-support "^1.1.2"
|
||||
console-control-strings "^1.0.0"
|
||||
has-unicode "^2.0.1"
|
||||
object-assign "^4.1.1"
|
||||
signal-exit "^3.0.0"
|
||||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
wide-align "^1.1.2"
|
||||
|
||||
gensync@^1.0.0-beta.2:
|
||||
version "1.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
|
|
@ -7710,6 +7774,11 @@ has-tostringtag@^1.0.0:
|
|||
dependencies:
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
has-unicode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
|
||||
|
||||
has-value@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||
|
|
@ -8000,7 +8069,7 @@ https-browserify@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
|
||||
https-proxy-agent@^5.0.1:
|
||||
https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||
|
|
@ -10265,6 +10334,11 @@ mimic-fn@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-response@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
||||
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
|
||||
|
||||
mimic-response@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
|
|
@ -10367,10 +10441,10 @@ minipass@^3.0.0, minipass@^3.1.1:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81"
|
||||
integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==
|
||||
minipass@^5.0.0, "minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
|
||||
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
|
||||
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
|
|
@ -10716,6 +10790,13 @@ non-layered-tidy-tree-layout@^2.0.2:
|
|||
resolved "https://registry.yarnpkg.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz#57d35d13c356643fc296a55fb11ac15e74da7804"
|
||||
integrity sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==
|
||||
|
||||
nopt@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
nopt@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
|
||||
|
|
@ -10764,6 +10845,16 @@ npm-run-path@^4.0.1:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npmlog@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0"
|
||||
integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==
|
||||
dependencies:
|
||||
are-we-there-yet "^2.0.0"
|
||||
console-control-strings "^1.1.0"
|
||||
gauge "^3.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
|
||||
nth-check@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||
|
|
@ -11173,6 +11264,18 @@ path-type@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8"
|
||||
integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==
|
||||
|
||||
path2d-polyfill@^2.0.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path2d-polyfill/-/path2d-polyfill-2.1.1.tgz#6098b7bf2fc24c306c6377bcd558b17ba437ea27"
|
||||
integrity sha512-4Rka5lN+rY/p0CdD8+E+BFv51lFaFvJOrlOhyQ+zjzyQrzyh3ozmxd1vVGGDdIbUFSBtIZLSnspxTgPT0iJhvA==
|
||||
dependencies:
|
||||
path2d "0.1.1"
|
||||
|
||||
path2d@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path2d/-/path2d-0.1.1.tgz#d3c3886cd2252fb2a7830c27ea7bb9a862d937ea"
|
||||
integrity sha512-/+S03c8AGsDYKKBtRDqieTJv2GlkMb0bWjnqOgtF6MkjdUQ9a8ARAtxWf9NgKLGm2+WQr6+/tqJdU8HNGsIDoA==
|
||||
|
||||
pbkdf2@^3.0.3:
|
||||
version "3.0.14"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
|
||||
|
|
@ -11184,13 +11287,13 @@ pbkdf2@^3.0.3:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
pdfjs-dist@^2.16.105:
|
||||
version "2.16.105"
|
||||
resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.16.105.tgz#937b9c4a918f03f3979c88209d84c1ce90122c2a"
|
||||
integrity sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==
|
||||
dependencies:
|
||||
dommatrix "^1.0.3"
|
||||
web-streams-polyfill "^3.2.1"
|
||||
pdfjs-dist@^3.11.174:
|
||||
version "3.11.174"
|
||||
resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz#5ff47b80f2d58c8dd0d74f615e7c6a7e7e704c4b"
|
||||
integrity sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==
|
||||
optionalDependencies:
|
||||
canvas "^2.11.2"
|
||||
path2d-polyfill "^2.0.1"
|
||||
|
||||
picocolors@^0.2.1:
|
||||
version "0.2.1"
|
||||
|
|
@ -11935,7 +12038,7 @@ read-pkg@^5.2.0:
|
|||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.2:
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
|
|
@ -12614,7 +12717,7 @@ sigmund@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
|
||||
integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
|
||||
|
||||
signal-exit@^3.0.3, signal-exit@^3.0.7:
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.3, signal-exit@^3.0.7:
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
|
@ -12629,6 +12732,15 @@ simple-concat@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
|
||||
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
|
||||
|
||||
simple-get@^3.0.3:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55"
|
||||
integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==
|
||||
dependencies:
|
||||
decompress-response "^4.2.0"
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
simple-get@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
|
||||
|
|
@ -12931,16 +13043,7 @@ string-length@^4.0.1:
|
|||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
|
|
@ -12992,7 +13095,7 @@ string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@~1.1.1:
|
|||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
|
|
@ -13006,13 +13109,6 @@ strip-ansi@^5.2.0:
|
|||
dependencies:
|
||||
ansi-regex "^4.1.0"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.0.1, strip-ansi@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
|
|
@ -13321,14 +13417,14 @@ tar-stream@^2.1.4:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@^6.0.2:
|
||||
version "6.1.11"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
||||
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
||||
tar@^6.0.2, tar@^6.1.11:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
|
||||
integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minipass "^5.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
|
@ -14667,6 +14763,13 @@ which@^2.0.1:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
||||
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
||||
dependencies:
|
||||
string-width "^1.0.2 || 2 || 3 || 4"
|
||||
|
||||
wildcard@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
|
||||
|
|
@ -14692,7 +14795,7 @@ worker-loader@^3.0.8:
|
|||
loader-utils "^2.0.0"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
|
|
@ -14710,15 +14813,6 @@ wrap-ansi@^6.2.0:
|
|||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||
|
|
|
|||
Loading…
Reference in New Issue