Skip to content

Commit e42f791

Browse files
authored
Merge pull request #372 from contentstack/fix/DX-25034
fix(audit): honour skipConfirm in workflow and extension removal
2 parents 35bfeaa + a4f3ad4 commit e42f791

7 files changed

Lines changed: 153 additions & 15 deletions

File tree

‎.talismanrc‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fileignoreconfig:
2-
- filename: pnpm-lock.yaml
3-
ignore_detectors:
4-
- filecontent
5-
- base64content
2+
- filename: pnpm-lock.yaml
3+
checksum: 35bd025f9eb7818f84064c14832819fa45c25b7f81748bee911d60618baf5dd0
4+
- filename: packages/contentstack-audit/test/unit/modules/extensions.test.ts
5+
checksum: 548b6e10241eb38df4b92f2dec90987b555ed6b7c582846d539828854eb1dadc
66
version: '1.0'

‎packages/contentstack-audit/src/modules/extensions.ts‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,11 @@ export default class Extensions {
167167
} else {
168168
log.debug(`Extension ${title} has no valid content types or scope not found`, this.config.auditContext);
169169
cliux.print($t(commonMsg.EXTENSION_FIX_WARN, { title: title, uid }), { color: 'yellow' });
170-
const shouldDelete = this.config.flags.yes || (await cliux.confirm(commonMsg.EXTENSION_FIX_CONFIRMATION));
170+
const shouldDelete =
171+
this.config.flags['copy-dir'] ||
172+
this.config.flags['external-config']?.skipConfirm ||
173+
this.config.flags.yes ||
174+
(await cliux.confirm(commonMsg.EXTENSION_FIX_CONFIRMATION));
171175
if (shouldDelete) {
172176
log.debug(`Deleting extension: ${title} (${uid})`, this.config.auditContext);
173177
delete newExtensionSchema[uid];

‎packages/contentstack-audit/src/modules/workflows.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,12 @@ export default class Workflows {
223223

224224
cliux.print(warningMessage, { color: 'yellow' });
225225

226-
if (this.config.flags.yes || (await cliux.confirm(commonMsg.WORKFLOW_FIX_CONFIRMATION))) {
226+
if (
227+
this.config.flags['copy-dir'] ||
228+
this.config.flags['external-config']?.skipConfirm ||
229+
this.config.flags.yes ||
230+
(await cliux.confirm(commonMsg.WORKFLOW_FIX_CONFIRMATION))
231+
) {
227232
log.debug(`Deleting workflow ${name} (${uid})`, this.config.auditContext);
228233
delete newWorkflowSchema[workflow.uid];
229234
} else {

‎packages/contentstack-audit/test/unit/modules/extensions.test.ts‎

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ux, cliux } from '@contentstack/cli-utilities';
66

77
import config from '../../../src/config';
88
import { Extensions } from '../../../src/modules';
9-
import { $t, auditMsg } from '../../../src/messages';
9+
import { $t, auditMsg, commonMsg } from '../../../src/messages';
1010
import sinon from 'sinon';
1111
import { Extension } from '../../../src/types';
1212
import { mockLogger } from '../mock-logger';
@@ -387,4 +387,67 @@ describe('Extensions scope containing content_types uids', () => {
387387
},
388388
);
389389
});
390+
391+
describe('fixExtensionsScope confirmation before removing an extension', () => {
392+
class ExtensionsWithCapturedFix extends Extensions {
393+
public fixedExtensions: Record<string, Extension> = {};
394+
395+
async writeFixContent(fixedExtensions: Record<string, Extension>) {
396+
this.fixedExtensions = fixedExtensions;
397+
}
398+
}
399+
400+
// ext1 and ext2 are scoped only to missing content types, so the fix removes them.
401+
const createExtensions = (flags: Record<string, unknown>) =>
402+
new ExtensionsWithCapturedFix({
403+
moduleName: 'extensions',
404+
ctSchema: cloneDeep(require('./../mock/contents/extensions/ctSchema.json')),
405+
config: Object.assign(cloneDeep(config), {
406+
basePath: resolve(`./test/unit/mock/contents/extensions/invalidExtensions/`),
407+
flags,
408+
}),
409+
fix: true,
410+
});
411+
412+
it('should remove the extensions without prompting when external-config skipConfirm is set', async () => {
413+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
414+
const ext = createExtensions({ 'external-config': { skipConfirm: true } });
415+
416+
await ext.run();
417+
418+
expect(confirm.notCalled).to.be.true;
419+
expect(ext.fixedExtensions).to.not.have.any.keys('ext1', 'ext2');
420+
});
421+
422+
it('should remove the extensions without prompting when copy-dir is set', async () => {
423+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
424+
const ext = createExtensions({ 'copy-dir': true });
425+
426+
await ext.run();
427+
428+
expect(confirm.notCalled).to.be.true;
429+
expect(ext.fixedExtensions).to.not.have.any.keys('ext1', 'ext2');
430+
});
431+
432+
it('should remove the extensions without prompting when yes is set', async () => {
433+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
434+
const ext = createExtensions({ yes: true });
435+
436+
await ext.run();
437+
438+
expect(confirm.notCalled).to.be.true;
439+
expect(ext.fixedExtensions).to.not.have.any.keys('ext1', 'ext2');
440+
});
441+
442+
it('should ask once per extension to remove and keep them when the user declines', async () => {
443+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
444+
const ext = createExtensions({});
445+
446+
await ext.run();
447+
448+
expect(confirm.callCount).to.equal(2);
449+
expect(confirm.alwaysCalledWithExactly(commonMsg.EXTENSION_FIX_CONFIRMATION)).to.be.true;
450+
expect(ext.fixedExtensions).to.include.all.keys('ext1', 'ext2');
451+
});
452+
});
390453
});

‎packages/contentstack-audit/test/unit/modules/workflow.test.ts‎

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { resolve } from 'path';
33
import { fancy } from 'fancy-test';
44
import { expect } from 'chai';
55
import cloneDeep from 'lodash/cloneDeep';
6-
import { ux } from '@contentstack/cli-utilities';
6+
import { ux, cliux } from '@contentstack/cli-utilities';
77
import sinon from 'sinon';
88

99
import config from '../../../src/config';
1010
import { Workflows } from '../../../src/modules';
11-
import { $t, auditMsg } from '../../../src/messages';
11+
import { $t, auditMsg, commonMsg } from '../../../src/messages';
12+
import { Workflow } from '../../../src/types';
1213
import { values } from 'lodash';
1314
import { mockLogger } from '../mock-logger';
1415

@@ -147,4 +148,69 @@ describe('Workflows', () => {
147148
]);
148149
});
149150
});
151+
152+
describe('fixWorkflowSchema confirmation before removing a workflow', () => {
153+
class WorkflowsWithCapturedFix extends Workflows {
154+
public fixedWorkflows: Record<string, Workflow> = {};
155+
156+
async writeFixContent(newWorkflowSchema: Record<string, Workflow>) {
157+
this.fixedWorkflows = newWorkflowSchema;
158+
}
159+
}
160+
161+
const createWorkflows = (flags: Record<string, unknown>) =>
162+
new WorkflowsWithCapturedFix({
163+
moduleName: 'workflows',
164+
// Without ct2, every content type on wf3 is missing, so the fix removes wf3.
165+
ctSchema: cloneDeep(require('./../mock/contents/workflows/ctSchema.json')).filter(
166+
(ct: { uid: string }) => ct.uid !== 'ct2',
167+
),
168+
config: Object.assign(cloneDeep(config), {
169+
basePath: resolve(`./test/unit/mock/contents/`),
170+
branch: undefined,
171+
flags,
172+
}),
173+
fix: true,
174+
});
175+
176+
it('should remove the workflow without prompting when external-config skipConfirm is set', async () => {
177+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
178+
const wf = createWorkflows({ 'external-config': { skipConfirm: true } });
179+
180+
await wf.run();
181+
182+
expect(confirm.notCalled).to.be.true;
183+
expect(wf.fixedWorkflows).to.not.have.property('wf3');
184+
});
185+
186+
it('should remove the workflow without prompting when copy-dir is set', async () => {
187+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
188+
const wf = createWorkflows({ 'copy-dir': true });
189+
190+
await wf.run();
191+
192+
expect(confirm.notCalled).to.be.true;
193+
expect(wf.fixedWorkflows).to.not.have.property('wf3');
194+
});
195+
196+
it('should remove the workflow without prompting when yes is set', async () => {
197+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
198+
const wf = createWorkflows({ yes: true });
199+
200+
await wf.run();
201+
202+
expect(confirm.notCalled).to.be.true;
203+
expect(wf.fixedWorkflows).to.not.have.property('wf3');
204+
});
205+
206+
it('should ask once per workflow to remove and keep it when the user declines', async () => {
207+
const confirm = sinon.stub(cliux, 'confirm').resolves(false);
208+
const wf = createWorkflows({});
209+
210+
await wf.run();
211+
212+
expect(confirm.calledOnceWithExactly(commonMsg.WORKFLOW_FIX_CONFIRMATION)).to.be.true;
213+
expect(wf.fixedWorkflows).to.have.property('wf3');
214+
});
215+
});
150216
});

‎pnpm-lock.yaml‎

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pnpm-workspace.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ overrides:
77
brace-expansion: 5.0.12
88
js-yaml: 5.4.2
99
fast-uri: 4.2.1
10-
ws: 8.21.3
10+
ws: 8.22.0

0 commit comments

Comments
 (0)