mirror of
https://github.com/strapi/strapi.git
synced 2025-12-14 00:29:32 +00:00
fix signals and add messaging for specific features
This commit is contained in:
parent
58b8c18870
commit
ff82ffff62
@ -5,6 +5,7 @@ import { isEmpty, uniq, last, isNumber, difference, omit, set } from 'lodash/fp'
|
|||||||
import { diff as semverDiff } from 'semver';
|
import { diff as semverDiff } from 'semver';
|
||||||
import type { Schema } from '@strapi/strapi';
|
import type { Schema } from '@strapi/strapi';
|
||||||
|
|
||||||
|
import chalk from 'chalk';
|
||||||
import type {
|
import type {
|
||||||
IAsset,
|
IAsset,
|
||||||
IDestinationProvider,
|
IDestinationProvider,
|
||||||
@ -567,7 +568,11 @@ class TransferEngine<
|
|||||||
|
|
||||||
// Cause an ongoing transfer to abort gracefully
|
// Cause an ongoing transfer to abort gracefully
|
||||||
async abortTransfer(): Promise<void> {
|
async abortTransfer(): Promise<void> {
|
||||||
this.#currentStream?.destroy(new TransferEngineError('fatal', 'Transfer aborted.'));
|
const err = new TransferEngineError('fatal', 'Transfer aborted.');
|
||||||
|
if (!this.#currentStream) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
this.#currentStream?.destroy(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<void> {
|
async init(): Promise<void> {
|
||||||
@ -659,12 +664,62 @@ class TransferEngine<
|
|||||||
destination: this.destinationProvider,
|
destination: this.destinationProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let workflowsStatus;
|
||||||
|
const source = 'Schema Integrity';
|
||||||
|
|
||||||
Object.entries(context.diffs).forEach(([uid, diffs]) => {
|
Object.entries(context.diffs).forEach(([uid, diffs]) => {
|
||||||
for (const diff of diffs) {
|
for (const diff of diffs) {
|
||||||
this.#reportWarning(`${diff.path.join('.')} for ${uid}`, 'Schema Integrity Check');
|
const path = `${uid}.${diff.path.join('.')}`;
|
||||||
|
const endPath = diff.path[diff.path.length - 1];
|
||||||
|
|
||||||
|
// Catch known features
|
||||||
|
// TODO: can this be moved outside of the engine?
|
||||||
|
if (
|
||||||
|
uid === 'admin::workflow' ||
|
||||||
|
uid === 'admin::workflow-stage' ||
|
||||||
|
endPath.startsWith('strapi_reviewWorkflows_')
|
||||||
|
) {
|
||||||
|
workflowsStatus = diff.kind;
|
||||||
|
}
|
||||||
|
// handle generic cases
|
||||||
|
else if (diff.kind === 'added') {
|
||||||
|
this.#reportWarning(
|
||||||
|
chalk.red(`${chalk.bold(path)} does not exist on destination`),
|
||||||
|
source
|
||||||
|
);
|
||||||
|
} else if (diff.kind === 'deleted') {
|
||||||
|
this.#reportWarning(
|
||||||
|
chalk.red(`${chalk.bold(path)} does not exist on source`),
|
||||||
|
source
|
||||||
|
);
|
||||||
|
} else if (diff.kind === 'modified') {
|
||||||
|
this.#reportWarning(
|
||||||
|
chalk.red(`${chalk.bold(path)} has a different data type`),
|
||||||
|
source
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// output the known feature warnings
|
||||||
|
if (workflowsStatus === 'added') {
|
||||||
|
this.#reportWarning(
|
||||||
|
chalk.red(`Review workflows feature does not exist on destination`),
|
||||||
|
source
|
||||||
|
);
|
||||||
|
} else if (workflowsStatus === 'deleted') {
|
||||||
|
this.#reportWarning(
|
||||||
|
chalk.red(`Review workflows feature does not exist on source`),
|
||||||
|
source
|
||||||
|
);
|
||||||
|
} else if (workflowsStatus === 'modified') {
|
||||||
|
this.#panic(
|
||||||
|
new TransferEngineInitializationError(
|
||||||
|
'Unresolved differences in schema [review workflows]'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await runMiddleware(context, this.#handlers.schemaDiff);
|
await runMiddleware(context, this.#handlers.schemaDiff);
|
||||||
|
|
||||||
if (Object.keys(context.diffs).length) {
|
if (Object.keys(context.diffs).length) {
|
||||||
|
|||||||
@ -25,6 +25,7 @@ const {
|
|||||||
exitMessageText,
|
exitMessageText,
|
||||||
abortTransfer,
|
abortTransfer,
|
||||||
getTransferTelemetryPayload,
|
getTransferTelemetryPayload,
|
||||||
|
setSignalHandler,
|
||||||
} = require('../../utils/data-transfer');
|
} = require('../../utils/data-transfer');
|
||||||
const { exitWith } = require('../../utils/helpers');
|
const { exitWith } = require('../../utils/helpers');
|
||||||
|
|
||||||
@ -115,10 +116,7 @@ module.exports = async (opts) => {
|
|||||||
let outFile;
|
let outFile;
|
||||||
try {
|
try {
|
||||||
// Abort transfer if user interrupts process
|
// Abort transfer if user interrupts process
|
||||||
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
|
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
||||||
process.removeAllListeners(signal);
|
|
||||||
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
||||||
});
|
|
||||||
|
|
||||||
results = await engine.transfer();
|
results = await engine.transfer();
|
||||||
outFile = results.destination.file.path;
|
outFile = results.destination.file.path;
|
||||||
|
|||||||
@ -21,6 +21,7 @@ const {
|
|||||||
exitMessageText,
|
exitMessageText,
|
||||||
abortTransfer,
|
abortTransfer,
|
||||||
getTransferTelemetryPayload,
|
getTransferTelemetryPayload,
|
||||||
|
setSignalHandler,
|
||||||
} = require('../../utils/data-transfer');
|
} = require('../../utils/data-transfer');
|
||||||
const { exitWith } = require('../../utils/helpers');
|
const { exitWith } = require('../../utils/helpers');
|
||||||
const { confirmMessage } = require('../../utils/commander');
|
const { confirmMessage } = require('../../utils/commander');
|
||||||
@ -113,6 +114,12 @@ module.exports = async (opts) => {
|
|||||||
const { updateLoader } = loadersFactory();
|
const { updateLoader } = loadersFactory();
|
||||||
|
|
||||||
engine.onSchemaDiff(async (context, next) => {
|
engine.onSchemaDiff(async (context, next) => {
|
||||||
|
// if we abort here, we need to actually exit the process because of conflict with inquirer prompt
|
||||||
|
setSignalHandler(async () => {
|
||||||
|
await abortTransfer({ engine, strapi });
|
||||||
|
exitWith(1, exitMessageText('import', true));
|
||||||
|
});
|
||||||
|
|
||||||
const confirmed = await confirmMessage(
|
const confirmed = await confirmMessage(
|
||||||
'There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?',
|
'There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?',
|
||||||
{
|
{
|
||||||
@ -120,6 +127,9 @@ module.exports = async (opts) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// reset handler back to normal
|
||||||
|
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
||||||
|
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
context.diffs = [];
|
context.diffs = [];
|
||||||
return next(context);
|
return next(context);
|
||||||
@ -151,10 +161,7 @@ module.exports = async (opts) => {
|
|||||||
let results;
|
let results;
|
||||||
try {
|
try {
|
||||||
// Abort transfer if user interrupts process
|
// Abort transfer if user interrupts process
|
||||||
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
|
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
||||||
process.removeAllListeners(signal);
|
|
||||||
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
||||||
});
|
|
||||||
|
|
||||||
results = await engine.transfer();
|
results = await engine.transfer();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ const {
|
|||||||
exitMessageText,
|
exitMessageText,
|
||||||
abortTransfer,
|
abortTransfer,
|
||||||
getTransferTelemetryPayload,
|
getTransferTelemetryPayload,
|
||||||
|
setSignalHandler,
|
||||||
} = require('../../utils/data-transfer');
|
} = require('../../utils/data-transfer');
|
||||||
const { exitWith } = require('../../utils/helpers');
|
const { exitWith } = require('../../utils/helpers');
|
||||||
const { confirmMessage } = require('../../utils/commander');
|
const { confirmMessage } = require('../../utils/commander');
|
||||||
@ -148,6 +149,12 @@ module.exports = async (opts) => {
|
|||||||
const { updateLoader } = loadersFactory();
|
const { updateLoader } = loadersFactory();
|
||||||
|
|
||||||
engine.onSchemaDiff(async (context, next) => {
|
engine.onSchemaDiff(async (context, next) => {
|
||||||
|
// if we abort here, we need to actually exit the process because of conflict with inquirer prompt
|
||||||
|
setSignalHandler(async () => {
|
||||||
|
await abortTransfer({ engine, strapi });
|
||||||
|
exitWith(1, exitMessageText('transfer', true));
|
||||||
|
});
|
||||||
|
|
||||||
const confirmed = await confirmMessage(
|
const confirmed = await confirmMessage(
|
||||||
'There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?',
|
'There are differences in schema between the source and destination, and the data listed above will be lost. Are you sure you want to continue?',
|
||||||
{
|
{
|
||||||
@ -155,6 +162,9 @@ module.exports = async (opts) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// reset handler back to normal
|
||||||
|
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
||||||
|
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
context.diffs = [];
|
context.diffs = [];
|
||||||
return next(context);
|
return next(context);
|
||||||
@ -188,10 +198,7 @@ module.exports = async (opts) => {
|
|||||||
let results;
|
let results;
|
||||||
try {
|
try {
|
||||||
// Abort transfer if user interrupts process
|
// Abort transfer if user interrupts process
|
||||||
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
|
setSignalHandler(() => abortTransfer({ engine, strapi }));
|
||||||
process.removeAllListeners(signal);
|
|
||||||
process.on(signal, () => abortTransfer({ engine, strapi }));
|
|
||||||
});
|
|
||||||
|
|
||||||
results = await engine.transfer();
|
results = await engine.transfer();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@ -113,6 +113,15 @@ const abortTransfer = async ({ engine, strapi }) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setSignalHandler = async (handler, signals = ['SIGINT', 'SIGTERM', 'SIGQUIT']) => {
|
||||||
|
signals.forEach((signal) => {
|
||||||
|
// We specifically remove ALL listeners because we have to clear the one added in Strapi bootstrap that has a process.exit
|
||||||
|
// TODO: Ideally Strapi bootstrap would not add that listener, and then this could be more flexible and add/remove only what it needs to
|
||||||
|
process.removeAllListeners(signal);
|
||||||
|
process.on(signal, handler);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const createStrapiInstance = async (opts = {}) => {
|
const createStrapiInstance = async (opts = {}) => {
|
||||||
try {
|
try {
|
||||||
const appContext = await strapi.compile();
|
const appContext = await strapi.compile();
|
||||||
@ -271,4 +280,5 @@ module.exports = {
|
|||||||
validateExcludeOnly,
|
validateExcludeOnly,
|
||||||
formatDiagnostic,
|
formatDiagnostic,
|
||||||
abortTransfer,
|
abortTransfer,
|
||||||
|
setSignalHandler,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user