@squiz/dxp-cli-next 5.33.0-develop.2 → 5.33.0-develop.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/migration/batch-get/batch-get.d.ts +3 -0
- package/lib/migration/batch-get/batch-get.js +45 -0
- package/lib/migration/batch-get/batch-get.spec.js +182 -0
- package/lib/migration/batch-next/batch-next.d.ts +3 -0
- package/lib/migration/batch-next/batch-next.js +60 -0
- package/lib/migration/batch-next/batch-next.spec.d.ts +1 -0
- package/lib/migration/batch-next/batch-next.spec.js +251 -0
- package/lib/migration/batch-revert/batch-revert.d.ts +3 -0
- package/lib/migration/batch-revert/batch-revert.js +45 -0
- package/lib/migration/batch-revert/batch-revert.spec.d.ts +1 -0
- package/lib/migration/batch-revert/batch-revert.spec.js +197 -0
- package/lib/migration/create/create.js +27 -7
- package/lib/migration/create/create.spec.js +48 -20
- package/lib/migration/get/get.js +3 -3
- package/lib/migration/get/get.spec.js +8 -19
- package/lib/migration/index.js +9 -1
- package/lib/migration/list/list.spec.js +7 -6
- package/lib/migration/mark-deployed/mark-deployed.d.ts +3 -0
- package/lib/migration/mark-deployed/mark-deployed.js +55 -0
- package/lib/migration/mark-deployed/mark-deployed.spec.d.ts +1 -0
- package/lib/migration/mark-deployed/mark-deployed.spec.js +217 -0
- package/lib/migration/next/next.spec.js +6 -5
- package/lib/migration/pre/pre.js +3 -3
- package/lib/migration/pre/pre.spec.js +8 -8
- package/lib/migration/revert/revert.js +1 -1
- package/lib/migration/revert/revert.spec.js +1 -1
- package/lib/migration/settings/settings.spec.js +2 -2
- package/lib/migration/types/common.types.d.ts +33 -2
- package/lib/migration/types/common.types.js +17 -0
- package/lib/migration/types/createMigration.types.d.ts +41 -3
- package/lib/migration/types/getMigration.types.d.ts +5 -1
- package/lib/migration/types/index.d.ts +1 -0
- package/lib/migration/types/index.js +1 -0
- package/lib/migration/types/markDeployed.types.d.ts +20 -0
- package/lib/migration/types/markDeployed.types.js +2 -0
- package/lib/migration/types/nextStage.types.d.ts +22 -1
- package/lib/migration/types/revert.types.d.ts +12 -0
- package/lib/migration/utils/common.d.ts +17 -3
- package/lib/migration/utils/common.js +56 -24
- package/lib/migration/utils/common.spec.js +73 -2
- package/lib/migration/utils/createMigration.d.ts +4 -21
- package/lib/migration/utils/createMigration.js +23 -32
- package/lib/migration/utils/createMigration.spec.js +19 -18
- package/lib/migration/utils/getMigration.d.ts +2 -1
- package/lib/migration/utils/getMigration.js +23 -18
- package/lib/migration/utils/getMigration.spec.js +146 -7
- package/lib/migration/utils/index.d.ts +1 -0
- package/lib/migration/utils/index.js +1 -0
- package/lib/migration/utils/listMigrations.spec.js +7 -6
- package/lib/migration/utils/loadAssetIdsFromFile.d.ts +9 -0
- package/lib/migration/utils/loadAssetIdsFromFile.js +40 -0
- package/lib/migration/utils/loadAssetIdsFromFile.spec.d.ts +1 -0
- package/lib/migration/utils/{loadCctIdsFromFile.spec.js → loadAssetIdsFromFile.spec.js} +13 -13
- package/lib/migration/utils/loadStageOptionsFromFile.d.ts +2 -1
- package/lib/migration/utils/markComponentsDeployed.d.ts +2 -0
- package/lib/migration/utils/markComponentsDeployed.js +37 -0
- package/lib/migration/utils/markComponentsDeployed.spec.d.ts +1 -0
- package/lib/migration/utils/markComponentsDeployed.spec.js +222 -0
- package/lib/migration/utils/nextStage.d.ts +2 -1
- package/lib/migration/utils/nextStage.js +32 -22
- package/lib/migration/utils/nextStage.spec.js +179 -7
- package/lib/migration/utils/options.d.ts +4 -1
- package/lib/migration/utils/options.js +32 -2
- package/lib/migration/utils/revertMigration.d.ts +2 -1
- package/lib/migration/utils/revertMigration.js +21 -1
- package/lib/migration/utils/revertMigration.spec.js +115 -0
- package/lib/page/utils/definitions.js +1 -1
- package/lib/page/utils/definitions.spec.js +19 -8
- package/package.json +1 -1
- package/lib/migration/utils/loadCctIdsFromFile.d.ts +0 -1
- package/lib/migration/utils/loadCctIdsFromFile.js +0 -32
- /package/lib/migration/{utils/loadCctIdsFromFile.spec.d.ts → batch-get/batch-get.spec.d.ts} +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
const nock_1 = __importDefault(require("nock"));
|
|
39
|
+
const batch_revert_1 = __importDefault(require("./batch-revert"));
|
|
40
|
+
const utils = __importStar(require("../utils/common"));
|
|
41
|
+
const ApplicationStore = __importStar(require("../../ApplicationStore"));
|
|
42
|
+
const revertMigrationModule = __importStar(require("../utils/revertMigration"));
|
|
43
|
+
jest.mock('../utils/common');
|
|
44
|
+
jest.mock('../utils/revertMigration');
|
|
45
|
+
jest.mock('../../ApplicationStore');
|
|
46
|
+
const mockUtils = utils;
|
|
47
|
+
const mockRevertMigration = revertMigrationModule;
|
|
48
|
+
const mockApplicationStore = ApplicationStore;
|
|
49
|
+
describe('batchRevertMigrationCommand', () => {
|
|
50
|
+
let logSpy;
|
|
51
|
+
let mockBatchRevertMigrationResponse;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
nock_1.default.cleanAll();
|
|
54
|
+
jest.clearAllMocks();
|
|
55
|
+
jest.resetAllMocks();
|
|
56
|
+
logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
57
|
+
mockApplicationStore.getApplicationFile.mockResolvedValue('session-cookie');
|
|
58
|
+
mockUtils.throwErrorIfNotLoggedIn.mockResolvedValue(undefined);
|
|
59
|
+
mockBatchRevertMigrationResponse = {
|
|
60
|
+
success: [{ assetIds: ['asset-1', 'asset-2'], message: 'Reverted' }],
|
|
61
|
+
failed: [],
|
|
62
|
+
};
|
|
63
|
+
mockRevertMigration.batchRevertMigration.mockResolvedValue(mockBatchRevertMigrationResponse);
|
|
64
|
+
});
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
logSpy.mockRestore();
|
|
67
|
+
});
|
|
68
|
+
describe('successful batch revert execution', () => {
|
|
69
|
+
it('should execute batch revert successfully with required options', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
|
+
const program = (0, batch_revert_1.default)();
|
|
71
|
+
yield program.parseAsync([
|
|
72
|
+
'node',
|
|
73
|
+
'dxp-cli',
|
|
74
|
+
'--migration-id',
|
|
75
|
+
'migration-123',
|
|
76
|
+
]);
|
|
77
|
+
expect(mockUtils.throwErrorIfNotLoggedIn).toHaveBeenCalledWith(program);
|
|
78
|
+
expect(mockRevertMigration.batchRevertMigration).toHaveBeenCalledWith({
|
|
79
|
+
migrationId: 'migration-123',
|
|
80
|
+
});
|
|
81
|
+
expect(mockRevertMigration.batchRevertMigration).toHaveBeenCalledTimes(1);
|
|
82
|
+
expect(mockUtils.handleCommandError).not.toHaveBeenCalled();
|
|
83
|
+
}));
|
|
84
|
+
it('should execute batch revert with tenant option', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
+
const program = (0, batch_revert_1.default)();
|
|
86
|
+
yield program.parseAsync([
|
|
87
|
+
'node',
|
|
88
|
+
'dxp-cli',
|
|
89
|
+
'--migration-id',
|
|
90
|
+
'migration-123',
|
|
91
|
+
'--tenant',
|
|
92
|
+
'test-tenant',
|
|
93
|
+
]);
|
|
94
|
+
expect(mockRevertMigration.batchRevertMigration).toHaveBeenCalledWith({
|
|
95
|
+
migrationId: 'migration-123',
|
|
96
|
+
tenant: 'test-tenant',
|
|
97
|
+
});
|
|
98
|
+
}));
|
|
99
|
+
it('should execute batch revert with override URL when environment variable is set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
100
|
+
const originalEnv = process.env.ENABLE_OVERRIDE_MIGRATION_URL;
|
|
101
|
+
process.env.ENABLE_OVERRIDE_MIGRATION_URL = 'true';
|
|
102
|
+
const program = (0, batch_revert_1.default)();
|
|
103
|
+
yield program.parseAsync([
|
|
104
|
+
'node',
|
|
105
|
+
'dxp-cli',
|
|
106
|
+
'--migration-id',
|
|
107
|
+
'migration-123',
|
|
108
|
+
'--overrideUrl',
|
|
109
|
+
'https://custom.migration.url',
|
|
110
|
+
]);
|
|
111
|
+
expect(mockRevertMigration.batchRevertMigration).toHaveBeenCalledWith({
|
|
112
|
+
migrationId: 'migration-123',
|
|
113
|
+
overrideUrl: 'https://custom.migration.url',
|
|
114
|
+
});
|
|
115
|
+
process.env.ENABLE_OVERRIDE_MIGRATION_URL = originalEnv;
|
|
116
|
+
}));
|
|
117
|
+
it('should handle mixed success and failure response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
+
mockBatchRevertMigrationResponse = {
|
|
119
|
+
success: [{ assetIds: ['asset-1'], message: 'Reverted' }],
|
|
120
|
+
failed: [{ assetIds: ['asset-2'], error: 'Cannot revert' }],
|
|
121
|
+
};
|
|
122
|
+
mockRevertMigration.batchRevertMigration.mockResolvedValue(mockBatchRevertMigrationResponse);
|
|
123
|
+
const program = (0, batch_revert_1.default)();
|
|
124
|
+
yield program.parseAsync([
|
|
125
|
+
'node',
|
|
126
|
+
'dxp-cli',
|
|
127
|
+
'--migration-id',
|
|
128
|
+
'migration-123',
|
|
129
|
+
]);
|
|
130
|
+
expect(mockRevertMigration.batchRevertMigration).toHaveBeenCalledTimes(1);
|
|
131
|
+
expect(mockUtils.handleCommandError).not.toHaveBeenCalled();
|
|
132
|
+
}));
|
|
133
|
+
});
|
|
134
|
+
describe('error scenarios', () => {
|
|
135
|
+
it('should handle batchRevertMigration API error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
const apiError = new Error('Failed to revert migration');
|
|
137
|
+
mockRevertMigration.batchRevertMigration.mockRejectedValue(apiError);
|
|
138
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
139
|
+
const program = (0, batch_revert_1.default)();
|
|
140
|
+
yield program.parseAsync([
|
|
141
|
+
'node',
|
|
142
|
+
'dxp-cli',
|
|
143
|
+
'--migration-id',
|
|
144
|
+
'migration-123',
|
|
145
|
+
]);
|
|
146
|
+
expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, apiError);
|
|
147
|
+
}));
|
|
148
|
+
it('should handle network error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
const networkError = new Error('Network connection failed');
|
|
150
|
+
mockRevertMigration.batchRevertMigration.mockRejectedValue(networkError);
|
|
151
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
152
|
+
const program = (0, batch_revert_1.default)();
|
|
153
|
+
yield program.parseAsync([
|
|
154
|
+
'node',
|
|
155
|
+
'dxp-cli',
|
|
156
|
+
'--migration-id',
|
|
157
|
+
'migration-123',
|
|
158
|
+
]);
|
|
159
|
+
expect(mockUtils.handleCommandError).toHaveBeenCalledWith(program, networkError);
|
|
160
|
+
}));
|
|
161
|
+
});
|
|
162
|
+
describe('required options validation', () => {
|
|
163
|
+
it('should require migration-id option', () => {
|
|
164
|
+
const program = (0, batch_revert_1.default)().exitOverride();
|
|
165
|
+
expect(() => {
|
|
166
|
+
program.parse(['node', 'dxp-cli']);
|
|
167
|
+
}).toThrow();
|
|
168
|
+
});
|
|
169
|
+
it('should not require tenant option', () => {
|
|
170
|
+
const program = (0, batch_revert_1.default)().exitOverride();
|
|
171
|
+
expect(() => {
|
|
172
|
+
program.parse(['node', 'dxp-cli', '--migration-id', 'migration-123']);
|
|
173
|
+
}).not.toThrow();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('command configuration', () => {
|
|
177
|
+
it('should have correct command name and description', () => {
|
|
178
|
+
const program = (0, batch_revert_1.default)();
|
|
179
|
+
expect(program.name()).toBe('batch-revert');
|
|
180
|
+
expect(program.description()).toBe('Revert all assets with stage "morph" and status "awaiting-confirmation" in a migration batch using the AI Page migration service');
|
|
181
|
+
});
|
|
182
|
+
it('should parse options correctly', () => {
|
|
183
|
+
const program = (0, batch_revert_1.default)();
|
|
184
|
+
program.parse([
|
|
185
|
+
'node',
|
|
186
|
+
'dxp-cli',
|
|
187
|
+
'--migration-id',
|
|
188
|
+
'migration-123',
|
|
189
|
+
'--tenant',
|
|
190
|
+
'test-tenant',
|
|
191
|
+
]);
|
|
192
|
+
const opts = program.opts();
|
|
193
|
+
expect(opts.migrationId).toBe('migration-123');
|
|
194
|
+
expect(opts.tenant).toBe('test-tenant');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
@@ -8,6 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
11
22
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
24
|
};
|
|
@@ -16,32 +27,41 @@ const commander_1 = require("commander");
|
|
|
16
27
|
const chalk_1 = __importDefault(require("chalk"));
|
|
17
28
|
const ora_1 = __importDefault(require("ora"));
|
|
18
29
|
const utils_1 = require("../utils");
|
|
19
|
-
const
|
|
30
|
+
const loadAssetIdsFromFile_1 = require("../utils/loadAssetIdsFromFile");
|
|
20
31
|
const createMigrationCommand = () => {
|
|
21
32
|
const createCommand = new commander_1.Command('create')
|
|
22
33
|
.name('create')
|
|
23
34
|
.description('Create a new migration using the AI Page Migration service')
|
|
24
|
-
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.ASSET_ID))
|
|
25
|
-
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.
|
|
35
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.ASSET_ID, false))
|
|
36
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.ASSET_IDS, false))
|
|
37
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.PREVIEW_ASSET_ID, false))
|
|
26
38
|
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.MATRIX_URL))
|
|
27
39
|
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.CCT_IDS, false))
|
|
40
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.STAGE_OPTIONS, false))
|
|
41
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.TRIGGER_NEXT_STAGE, false))
|
|
28
42
|
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.TENANT, false))
|
|
29
43
|
.configureOutput({
|
|
30
44
|
outputError(str, write) {
|
|
31
45
|
write(chalk_1.default.red(str));
|
|
32
46
|
},
|
|
33
47
|
})
|
|
34
|
-
.action((
|
|
48
|
+
.action((_a) => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
var { stageOptions: stageOptionsPath, cctIds: cctIdsPath, assetIds: assetIdsPath, assetId } = _a, options = __rest(_a, ["stageOptions", "cctIds", "assetIds", "assetId"]);
|
|
35
50
|
yield (0, utils_1.throwErrorIfNotLoggedIn)(createCommand);
|
|
36
51
|
const spinner = (0, ora_1.default)('Creating migration').start();
|
|
37
52
|
try {
|
|
38
|
-
const cctIds = (0,
|
|
53
|
+
const cctIds = (0, loadAssetIdsFromFile_1.loadAssetIdsFromFile)(cctIdsPath, 'cct');
|
|
54
|
+
const assetIds = (0, loadAssetIdsFromFile_1.loadAssetIdsFromFile)(assetIdsPath, 'asset');
|
|
55
|
+
const stageOptions = (0, utils_1.loadStageOptionsFromFile)(stageOptionsPath);
|
|
56
|
+
if ((assetIds === null || assetIds === void 0 ? void 0 : assetIds.length) && assetId) {
|
|
57
|
+
throw new Error('Can only provide either asset-ids or asset-id, not both');
|
|
58
|
+
}
|
|
39
59
|
// Create migration
|
|
40
|
-
const response = yield (0, utils_1.createMigration)(Object.assign(Object.assign({}, options), { cctIds }));
|
|
60
|
+
const response = yield (0, utils_1.createMigration)(Object.assign(Object.assign({}, options), { cctIds, assetIds: assetIds !== null && assetIds !== void 0 ? assetIds : [assetId], stageOptions }));
|
|
41
61
|
if (!response) {
|
|
42
62
|
throw new Error('Migration creation failed');
|
|
43
63
|
}
|
|
44
|
-
spinner.succeed((0, utils_1.buildMigrationSuccessMessage)('migration', response
|
|
64
|
+
spinner.succeed((0, utils_1.buildMigrationSuccessMessage)('migration', response));
|
|
45
65
|
}
|
|
46
66
|
catch (error) {
|
|
47
67
|
spinner.fail();
|
|
@@ -39,10 +39,19 @@ const nock_1 = __importDefault(require("nock"));
|
|
|
39
39
|
const create_1 = __importDefault(require("./create"));
|
|
40
40
|
const utils = __importStar(require("../utils/common"));
|
|
41
41
|
const createMigration = __importStar(require("../utils/createMigration"));
|
|
42
|
+
const ApplicationStore = __importStar(require("../../ApplicationStore"));
|
|
43
|
+
const loadAssetIdsModule = __importStar(require("../utils/loadAssetIdsFromFile"));
|
|
44
|
+
const loadStageOptionsModule = __importStar(require("../utils/loadStageOptionsFromFile"));
|
|
42
45
|
jest.mock('../utils/common');
|
|
43
46
|
jest.mock('../utils/createMigration');
|
|
47
|
+
jest.mock('../../ApplicationStore');
|
|
48
|
+
jest.mock('../utils/loadAssetIdsFromFile');
|
|
49
|
+
jest.mock('../utils/loadStageOptionsFromFile');
|
|
44
50
|
const mockUtils = utils;
|
|
45
51
|
const mockCreateMigration = createMigration;
|
|
52
|
+
const mockApplicationStore = ApplicationStore;
|
|
53
|
+
const mockLoadAssetIds = loadAssetIdsModule;
|
|
54
|
+
const mockLoadStageOptions = loadStageOptionsModule;
|
|
46
55
|
describe('createMigrationCommand', () => {
|
|
47
56
|
let logSpy;
|
|
48
57
|
let mockCreateMigrationResponse;
|
|
@@ -51,8 +60,11 @@ describe('createMigrationCommand', () => {
|
|
|
51
60
|
jest.clearAllMocks();
|
|
52
61
|
jest.resetAllMocks();
|
|
53
62
|
logSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
63
|
+
mockApplicationStore.getApplicationFile.mockResolvedValue('session-cookie');
|
|
54
64
|
mockUtils.throwErrorIfNotLoggedIn.mockResolvedValue(undefined);
|
|
55
65
|
mockUtils.buildMigrationSuccessMessage.mockReturnValue('Migration created successfully');
|
|
66
|
+
mockLoadAssetIds.loadAssetIdsFromFile.mockReturnValue(undefined);
|
|
67
|
+
mockLoadStageOptions.loadStageOptionsFromFile.mockReturnValue(undefined);
|
|
56
68
|
mockCreateMigrationResponse = {
|
|
57
69
|
assetMigration: {
|
|
58
70
|
migrationId: 'migration-123',
|
|
@@ -87,9 +99,11 @@ describe('createMigrationCommand', () => {
|
|
|
87
99
|
]);
|
|
88
100
|
expect(mockUtils.throwErrorIfNotLoggedIn).toHaveBeenCalledWith(program);
|
|
89
101
|
expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
|
|
90
|
-
|
|
102
|
+
assetIds: ['asset-123'],
|
|
91
103
|
previewAssetId: 'preview-456',
|
|
92
104
|
matrixUrl: 'https://matrix.example.com',
|
|
105
|
+
cctIds: undefined,
|
|
106
|
+
stageOptions: undefined,
|
|
93
107
|
});
|
|
94
108
|
expect(mockCreateMigration.createMigration).toHaveBeenCalledTimes(1);
|
|
95
109
|
expect(mockUtils.handleCommandError).not.toHaveBeenCalled();
|
|
@@ -109,10 +123,12 @@ describe('createMigrationCommand', () => {
|
|
|
109
123
|
'test-tenant',
|
|
110
124
|
]);
|
|
111
125
|
expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
|
|
112
|
-
|
|
126
|
+
assetIds: ['asset-123'],
|
|
113
127
|
previewAssetId: 'preview-456',
|
|
114
128
|
matrixUrl: 'https://matrix.example.com',
|
|
115
129
|
tenant: 'test-tenant',
|
|
130
|
+
cctIds: undefined,
|
|
131
|
+
stageOptions: undefined,
|
|
116
132
|
});
|
|
117
133
|
}));
|
|
118
134
|
it('should create migration with override URL when environment variable is set', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -132,10 +148,12 @@ describe('createMigrationCommand', () => {
|
|
|
132
148
|
'https://custom.migration.url',
|
|
133
149
|
]);
|
|
134
150
|
expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
|
|
135
|
-
|
|
151
|
+
assetIds: ['asset-123'],
|
|
136
152
|
previewAssetId: 'preview-456',
|
|
137
153
|
matrixUrl: 'https://matrix.example.com',
|
|
138
154
|
overrideUrl: 'https://custom.migration.url',
|
|
155
|
+
cctIds: undefined,
|
|
156
|
+
stageOptions: undefined,
|
|
139
157
|
});
|
|
140
158
|
process.env.ENABLE_OVERRIDE_MIGRATION_URL = originalEnv;
|
|
141
159
|
}));
|
|
@@ -143,7 +161,7 @@ describe('createMigrationCommand', () => {
|
|
|
143
161
|
describe('error scenarios', () => {
|
|
144
162
|
it('should handle migration creation failure', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
145
163
|
mockCreateMigration.createMigration.mockResolvedValue(null);
|
|
146
|
-
mockUtils.handleCommandError.mockImplementation(() => { });
|
|
164
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
147
165
|
const program = (0, create_1.default)();
|
|
148
166
|
yield program.parseAsync([
|
|
149
167
|
'node',
|
|
@@ -160,7 +178,7 @@ describe('createMigrationCommand', () => {
|
|
|
160
178
|
it('should handle migration API error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
161
179
|
const apiError = new Error('Migration API failed');
|
|
162
180
|
mockCreateMigration.createMigration.mockRejectedValue(apiError);
|
|
163
|
-
mockUtils.handleCommandError.mockImplementation(() => { });
|
|
181
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
164
182
|
const program = (0, create_1.default)();
|
|
165
183
|
yield program.parseAsync([
|
|
166
184
|
'node',
|
|
@@ -194,20 +212,30 @@ describe('createMigrationCommand', () => {
|
|
|
194
212
|
}));
|
|
195
213
|
});
|
|
196
214
|
describe('required options validation', () => {
|
|
197
|
-
it('should
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
it('should allow assetId to be optional at command level for pre-migrations', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
216
|
+
// When creating a migration without assetId or assetIds, cctIds must be provided.
|
|
217
|
+
// This is called a "pre-migration" which converts CCTs before the actual migration.
|
|
218
|
+
// The command-level validation allows this, with the API handling the validation.
|
|
219
|
+
const program = (0, create_1.default)();
|
|
220
|
+
yield program.parseAsync([
|
|
221
|
+
'node',
|
|
222
|
+
'dxp-cli',
|
|
223
|
+
'--preview-asset-id',
|
|
224
|
+
'preview-456',
|
|
225
|
+
'--matrix-url',
|
|
226
|
+
'https://matrix.example.com',
|
|
227
|
+
]);
|
|
228
|
+
// When neither assetId nor assetIds is provided, createMigration is called with [undefined]
|
|
229
|
+
// In a real pre-migration scenario, cctIds would be provided instead
|
|
230
|
+
expect(mockCreateMigration.createMigration).toHaveBeenCalledWith({
|
|
231
|
+
assetIds: [undefined],
|
|
232
|
+
previewAssetId: 'preview-456',
|
|
233
|
+
matrixUrl: 'https://matrix.example.com',
|
|
234
|
+
cctIds: undefined,
|
|
235
|
+
stageOptions: undefined,
|
|
236
|
+
});
|
|
237
|
+
}));
|
|
238
|
+
it('should not require previewAssetId option', () => {
|
|
211
239
|
const program = (0, create_1.default)().exitOverride();
|
|
212
240
|
expect(() => {
|
|
213
241
|
program.parse([
|
|
@@ -218,7 +246,7 @@ describe('createMigrationCommand', () => {
|
|
|
218
246
|
'--matrix-url',
|
|
219
247
|
'https://matrix.example.com',
|
|
220
248
|
]);
|
|
221
|
-
}).toThrow();
|
|
249
|
+
}).not.toThrow();
|
|
222
250
|
});
|
|
223
251
|
it('should require matrixUrl option', () => {
|
|
224
252
|
const program = (0, create_1.default)().exitOverride();
|
package/lib/migration/get/get.js
CHANGED
|
@@ -19,9 +19,9 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
19
19
|
const getMigrationCommand = () => {
|
|
20
20
|
const getCommand = new commander_1.Command('get')
|
|
21
21
|
.name('get')
|
|
22
|
-
.description('Get a migration using the AI Page migration service')
|
|
22
|
+
.description('Get a migration for a given asset using the AI Page migration service')
|
|
23
23
|
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.MIGRATION_ID))
|
|
24
|
-
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.ASSET_ID
|
|
24
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.ASSET_ID))
|
|
25
25
|
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.TENANT, false))
|
|
26
26
|
.configureOutput({
|
|
27
27
|
outputError(str, write) {
|
|
@@ -29,8 +29,8 @@ const getMigrationCommand = () => {
|
|
|
29
29
|
},
|
|
30
30
|
})
|
|
31
31
|
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
-
const spinner = (0, ora_1.default)('Getting migration').start();
|
|
33
32
|
yield (0, utils_1.throwErrorIfNotLoggedIn)(getCommand);
|
|
33
|
+
const spinner = (0, ora_1.default)('Getting migration').start();
|
|
34
34
|
try {
|
|
35
35
|
const response = yield (0, utils_1.getMigration)(options);
|
|
36
36
|
spinner.succeed(`Migration details: ${JSON.stringify(response, null, 2)}`);
|
|
@@ -40,6 +40,7 @@ const get_1 = __importDefault(require("./get"));
|
|
|
40
40
|
const utils = __importStar(require("../utils/common"));
|
|
41
41
|
const ApplicationStore = __importStar(require("../../ApplicationStore"));
|
|
42
42
|
const getMigration = __importStar(require("../utils/getMigration"));
|
|
43
|
+
const types_1 = require("../types");
|
|
43
44
|
jest.mock('../utils/common');
|
|
44
45
|
jest.mock('../utils/getMigration');
|
|
45
46
|
jest.mock('../../ApplicationStore');
|
|
@@ -65,8 +66,8 @@ describe('getMigrationCommand', () => {
|
|
|
65
66
|
created: 1718230800,
|
|
66
67
|
updated: 1718230800,
|
|
67
68
|
migrationIdAssetId: 'migration-123-asset-456',
|
|
68
|
-
stage:
|
|
69
|
-
status:
|
|
69
|
+
stage: types_1.MigrationStage.create,
|
|
70
|
+
status: types_1.MigrationStatus.complete,
|
|
70
71
|
stageDetails: 'Migration completed successfully',
|
|
71
72
|
previewPageAssetId: 'preview-789',
|
|
72
73
|
componentsTarDownloadUrl: 'https://download.example.com/components.zip',
|
|
@@ -134,24 +135,12 @@ describe('getMigrationCommand', () => {
|
|
|
134
135
|
});
|
|
135
136
|
process.env.ENABLE_OVERRIDE_MIGRATION_URL = originalEnv;
|
|
136
137
|
}));
|
|
137
|
-
it('should get migration without asset-id option', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
138
|
-
const program = (0, get_1.default)();
|
|
139
|
-
yield program.parseAsync([
|
|
140
|
-
'node',
|
|
141
|
-
'dxp-cli',
|
|
142
|
-
'--migration-id',
|
|
143
|
-
'migration-123',
|
|
144
|
-
]);
|
|
145
|
-
expect(mockGetMigration.getMigration).toHaveBeenCalledWith({
|
|
146
|
-
migrationId: 'migration-123',
|
|
147
|
-
});
|
|
148
|
-
}));
|
|
149
138
|
});
|
|
150
139
|
describe('error scenarios', () => {
|
|
151
140
|
it('should handle getMigration API error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
141
|
const apiError = new Error('Migration not found');
|
|
153
142
|
mockGetMigration.getMigration.mockRejectedValue(apiError);
|
|
154
|
-
mockUtils.handleCommandError.mockImplementation(() => { });
|
|
143
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
155
144
|
const program = (0, get_1.default)();
|
|
156
145
|
yield program.parseAsync([
|
|
157
146
|
'node',
|
|
@@ -166,7 +155,7 @@ describe('getMigrationCommand', () => {
|
|
|
166
155
|
it('should handle network error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
167
156
|
const networkError = new Error('Network connection failed');
|
|
168
157
|
mockGetMigration.getMigration.mockRejectedValue(networkError);
|
|
169
|
-
mockUtils.handleCommandError.mockImplementation(() => { });
|
|
158
|
+
mockUtils.handleCommandError.mockImplementation((() => { }));
|
|
170
159
|
const program = (0, get_1.default)();
|
|
171
160
|
yield program.parseAsync([
|
|
172
161
|
'node',
|
|
@@ -186,18 +175,18 @@ describe('getMigrationCommand', () => {
|
|
|
186
175
|
program.parse(['node', 'dxp-cli', '--asset-id', 'asset-456']);
|
|
187
176
|
}).toThrow();
|
|
188
177
|
});
|
|
189
|
-
it('should
|
|
178
|
+
it('should require asset-id option', () => {
|
|
190
179
|
const program = (0, get_1.default)().exitOverride();
|
|
191
180
|
expect(() => {
|
|
192
181
|
program.parse(['node', 'dxp-cli', '--migration-id', 'migration-123']);
|
|
193
|
-
}).
|
|
182
|
+
}).toThrow();
|
|
194
183
|
});
|
|
195
184
|
});
|
|
196
185
|
describe('command configuration', () => {
|
|
197
186
|
it('should have correct command name and description', () => {
|
|
198
187
|
const program = (0, get_1.default)();
|
|
199
188
|
expect(program.name()).toBe('get');
|
|
200
|
-
expect(program.description()).toBe('Get a migration using the AI Page migration service');
|
|
189
|
+
expect(program.description()).toBe('Get a migration for a given asset using the AI Page migration service');
|
|
201
190
|
});
|
|
202
191
|
it('should parse options correctly', () => {
|
|
203
192
|
const program = (0, get_1.default)();
|
package/lib/migration/index.js
CHANGED
|
@@ -6,19 +6,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const commander_1 = require("commander");
|
|
7
7
|
const create_1 = __importDefault(require("./create/create"));
|
|
8
8
|
const get_1 = __importDefault(require("./get/get"));
|
|
9
|
+
const batch_get_1 = __importDefault(require("./batch-get/batch-get"));
|
|
9
10
|
const next_1 = __importDefault(require("./next/next"));
|
|
11
|
+
const batch_next_1 = __importDefault(require("./batch-next/batch-next"));
|
|
10
12
|
const pre_1 = __importDefault(require("./pre/pre"));
|
|
11
13
|
const settings_1 = __importDefault(require("./settings/settings"));
|
|
12
14
|
const revert_1 = __importDefault(require("./revert/revert"));
|
|
15
|
+
const batch_revert_1 = __importDefault(require("./batch-revert/batch-revert"));
|
|
13
16
|
const list_1 = __importDefault(require("./list/list"));
|
|
17
|
+
const mark_deployed_1 = __importDefault(require("./mark-deployed/mark-deployed"));
|
|
14
18
|
const migrationCommand = new commander_1.Command('migration');
|
|
15
19
|
migrationCommand
|
|
16
20
|
.description('AI Page Migration Service Commands')
|
|
17
21
|
.addCommand((0, create_1.default)())
|
|
18
22
|
.addCommand((0, get_1.default)())
|
|
23
|
+
.addCommand((0, batch_get_1.default)())
|
|
19
24
|
.addCommand((0, list_1.default)())
|
|
20
25
|
.addCommand((0, next_1.default)())
|
|
26
|
+
.addCommand((0, batch_next_1.default)())
|
|
21
27
|
.addCommand((0, pre_1.default)())
|
|
22
28
|
.addCommand((0, settings_1.default)())
|
|
23
|
-
.addCommand((0, revert_1.default)())
|
|
29
|
+
.addCommand((0, revert_1.default)())
|
|
30
|
+
.addCommand((0, batch_revert_1.default)())
|
|
31
|
+
.addCommand((0, mark_deployed_1.default)());
|
|
24
32
|
exports.default = migrationCommand;
|
|
@@ -39,6 +39,7 @@ const mockListMigrations = jest.fn();
|
|
|
39
39
|
const nock_1 = __importDefault(require("nock"));
|
|
40
40
|
const list_1 = __importDefault(require("./list"));
|
|
41
41
|
const utils = __importStar(require("../utils/common"));
|
|
42
|
+
const types_1 = require("../types");
|
|
42
43
|
jest.mock('../utils/common');
|
|
43
44
|
jest.mock('../utils/listMigrations', () => ({
|
|
44
45
|
listMigrations: mockListMigrations,
|
|
@@ -51,24 +52,24 @@ describe('listMigrationsCommand', () => {
|
|
|
51
52
|
{
|
|
52
53
|
migrationId: 'migration-1',
|
|
53
54
|
assetId: 'asset-1',
|
|
54
|
-
stage:
|
|
55
|
-
status:
|
|
55
|
+
stage: types_1.MigrationStage.morph,
|
|
56
|
+
status: types_1.MigrationStatus.complete,
|
|
56
57
|
created: 100,
|
|
57
58
|
updated: 200,
|
|
58
59
|
},
|
|
59
60
|
{
|
|
60
61
|
migrationId: 'migration-2',
|
|
61
62
|
assetId: 'asset-2',
|
|
62
|
-
stage:
|
|
63
|
-
status:
|
|
63
|
+
stage: types_1.MigrationStage.morph,
|
|
64
|
+
status: types_1.MigrationStatus.complete,
|
|
64
65
|
created: 100,
|
|
65
66
|
updated: 200,
|
|
66
67
|
},
|
|
67
68
|
{
|
|
68
69
|
migrationId: 'migration-3',
|
|
69
70
|
assetId: 'asset-3',
|
|
70
|
-
stage:
|
|
71
|
-
status:
|
|
71
|
+
stage: types_1.MigrationStage.morph,
|
|
72
|
+
status: types_1.MigrationStatus.complete,
|
|
72
73
|
created: 100,
|
|
73
74
|
updated: 200,
|
|
74
75
|
},
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const commander_1 = require("commander");
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const ora_1 = __importDefault(require("ora"));
|
|
18
|
+
const utils_1 = require("../utils");
|
|
19
|
+
const loadAssetIdsFromFile_1 = require("../utils/loadAssetIdsFromFile");
|
|
20
|
+
function formatMarkDeployedResult(success, failed) {
|
|
21
|
+
return (0, utils_1.formatBatchOperationResult)(success.length > 0
|
|
22
|
+
? [{ assetIds: success, message: 'marked as deployed' }]
|
|
23
|
+
: [], failed.map(({ cctId, error }) => ({ assetIds: [cctId], error })));
|
|
24
|
+
}
|
|
25
|
+
const markDeployedCommand = () => {
|
|
26
|
+
const markCommand = new commander_1.Command('mark-deployed')
|
|
27
|
+
.name('mark-deployed')
|
|
28
|
+
.description('Mark components as deployed in the AI Page Migration service')
|
|
29
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.CCT_IDS))
|
|
30
|
+
.addOption((0, utils_1.getParamOption)(utils_1.OptionName.TENANT, false))
|
|
31
|
+
.configureOutput({
|
|
32
|
+
outputError(str, write) {
|
|
33
|
+
write(chalk_1.default.red(str));
|
|
34
|
+
},
|
|
35
|
+
})
|
|
36
|
+
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
|
+
yield (0, utils_1.throwErrorIfNotLoggedIn)(markCommand);
|
|
38
|
+
const spinner = (0, ora_1.default)('Marking components as deployed').start();
|
|
39
|
+
try {
|
|
40
|
+
const cctIds = (0, loadAssetIdsFromFile_1.loadAssetIdsFromFile)(options.cctIds);
|
|
41
|
+
if (!cctIds || cctIds.length === 0) {
|
|
42
|
+
throw new Error('No CCT IDs provided');
|
|
43
|
+
}
|
|
44
|
+
const response = yield (0, utils_1.markComponentsDeployed)(Object.assign(Object.assign({}, options), { cctIds }));
|
|
45
|
+
spinner.succeed(formatMarkDeployedResult(response.success, response.failed));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
spinner.fail();
|
|
49
|
+
(0, utils_1.handleCommandError)(markCommand, error);
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
(0, utils_1.addOverrideUrlOption)(markCommand);
|
|
53
|
+
return markCommand;
|
|
54
|
+
};
|
|
55
|
+
exports.default = markDeployedCommand;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|