diff --git a/packages/cli-e2e/__tests__/orgResources.specs.ts b/packages/cli-e2e/__tests__/orgResources.specs.ts index 69a56e6bff..eb4236ffd2 100644 --- a/packages/cli-e2e/__tests__/orgResources.specs.ts +++ b/packages/cli-e2e/__tests__/orgResources.specs.ts @@ -3,7 +3,7 @@ import {CLI_EXEC_PATH, getConfig, getPathToHomedirEnvFile} from '../utils/cli'; import {ProcessManager} from '../utils/processManager'; import {Terminal} from '../utils/terminal/terminal'; import {config} from 'dotenv'; -import {ensureDirSync} from 'fs-extra'; +import {ensureDirSync, rmSync} from 'fs-extra'; import PlatformClient, {FieldTypes} from '@coveord/platform-client'; import {getPlatformClient} from '../utils/platform'; import {readdirSync} from 'fs'; @@ -92,13 +92,16 @@ describe('org:resources', () => { const pullFromOrg = async ( targetOrg: string, procManager: ProcessManager, - destinationPath: string + destinationPath: string, + additionalFlags: string[] = [] ) => { const args: string[] = [ CLI_EXEC_PATH, 'org:resources:pull', `-t=${targetOrg}`, + '-o', '--no-git', + ...additionalFlags, ]; const pullTerminal = createNewTerminal( @@ -250,8 +253,11 @@ describe('org:resources', () => { describe('org:resources:pull', () => { const destinationPath = join('new-snapshot-project'); + const getResourceFolderContent = (projectPath: string) => + readdirSync(join(projectPath, 'resources')); - beforeAll(() => { + beforeEach(() => { + rmSync(destinationPath, {recursive: true, force: true}); ensureDirSync(destinationPath); }); @@ -259,7 +265,6 @@ describe('org:resources', () => { "should pull the org's content", async () => { await pullFromOrg(testOrgId, processManager, destinationPath); - const snapshotFiles = readdirSync(snapshotProjectPath); const destinationFiles = readdirSync(destinationPath); @@ -267,6 +272,23 @@ describe('org:resources', () => { }, defaultTimeout ); + + it( + 'directory should only contains pulled resources', + async () => { + await pullFromOrg(testOrgId, processManager, destinationPath, [ + '-r=field', + ]); + const originalResources = getResourceFolderContent(snapshotProjectPath); + const destinationResources = getResourceFolderContent(destinationPath); + + expect(destinationResources.length).toBeGreaterThan(0); + expect(destinationResources.length).toBeLessThan( + originalResources.length + ); + }, + defaultTimeout + ); }); it('should not have any snapshot in the target org', async () => { diff --git a/packages/cli/src/commands/org/resources/pull.ts b/packages/cli/src/commands/org/resources/pull.ts index 2015c8007a..590b799acf 100644 --- a/packages/cli/src/commands/org/resources/pull.ts +++ b/packages/cli/src/commands/org/resources/pull.ts @@ -59,6 +59,11 @@ export default class Pull extends Command { default: true, allowNo: true, }), + overwrite: flags.boolean({ + char: 'o', + description: 'Overwrite resources directory if it exists.', + default: false, + }), }; public static hidden = true; @@ -70,10 +75,13 @@ export default class Pull extends Command { HasNecessaryCoveoPrivileges(writeSnapshotPrivilege) ) public async run() { + const project = new Project(this.projectPath); + await this.ensureProjectReset(project); + const snapshot = await this.getSnapshot(); cli.action.start('Updating project with Snapshot'); - await this.refreshProject(snapshot); + await this.refreshProject(project, snapshot); await snapshot.delete(); cli.action.stop('Project updated'); @@ -103,9 +111,8 @@ export default class Pull extends Command { } } - private async refreshProject(snapshot: Snapshot) { + private async refreshProject(project: Project, snapshot: Snapshot) { const {flags} = this.parse(Pull); - const project = new Project(this.projectPath); if (flags.git && !project.contains('.git')) { await spawnProcess('git', ['init', `${this.projectPath}`], { stdio: 'ignore', @@ -115,6 +122,21 @@ export default class Pull extends Command { await project.refresh(snapshotBlob); } + private async ensureProjectReset(project: Project) { + const {flags} = this.parse(Pull); + if (!flags.overwrite && project.contains(Project.resourceFolderName)) { + const overwrite = + await cli.confirm(dedent`There is already a Coveo project with resources in it. + This command will overwrite the ${Project.resourceFolderName} folder content, do you want to proceed? (y/n)`); + + if (!overwrite) { + this.exit(); + } + } + + project.reset(); + } + private async getSnapshot() { const {flags} = this.parse(Pull); const target = await getTargetOrg(this.configuration, flags.target); diff --git a/packages/cli/src/lib/project/project.ts b/packages/cli/src/lib/project/project.ts index 3f822ba2e9..940401d41d 100644 --- a/packages/cli/src/lib/project/project.ts +++ b/packages/cli/src/lib/project/project.ts @@ -4,6 +4,7 @@ import { readdirSync, unlinkSync, writeFileSync, + rmSync, } from 'fs'; import {extname, join} from 'path'; import {cli} from 'cli-ux'; @@ -14,7 +15,7 @@ import {DotFolder, DotFolderConfig} from './dotFolder'; import {readJsonSync, writeJsonSync, WriteOptions} from 'fs-extra'; export class Project { - private static readonly resourceFolderName = 'resources'; + public static readonly resourceFolderName = 'resources'; public static readonly jsonFormat: WriteOptions = {spaces: '\t'}; public constructor(private _pathToProject: string) { if (!this.isCoveoProject) { @@ -31,6 +32,12 @@ export class Project { this.deleteTemporaryZipFile(); } + public reset() { + if (this.isResourcesProject) { + rmSync(Project.resourceFolderName, {recursive: true, force: true}); + } + } + private formatResourceFiles(dirPath = this.resourcePath) { const files = readdirSync(dirPath, {withFileTypes: true}); files.forEach((file) => { @@ -98,6 +105,7 @@ export class Project { public get resourcePath() { return join(this._pathToProject, Project.resourceFolderName); } + public contains(fileName: string) { return existsSync(join(this.pathToProject, fileName)); }