From dabbd25d30785fd19c84f4b54508381f5a85b0b7 Mon Sep 17 00:00:00 2001 From: "Angel M. Adames" Date: Wed, 14 Feb 2024 17:09:28 -0400 Subject: [PATCH] chore: Add more clone command/tests --- .gitignore | 1 + src/commands/clone/index.ts | 16 ++++++++-------- src/commands/setup/index.ts | 4 ++-- src/utils/file-system.ts | 9 ++++++--- src/utils/git.ts | 3 ++- src/utils/shared-options.ts | 7 +++---- test/commands/clone.test.ts | 25 ++++++++++++++++++++++--- 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index c8e993c..bbb9190 100644 --- a/.gitignore +++ b/.gitignore @@ -177,3 +177,4 @@ dist # Build files dist/** ./dems +**/repos/ diff --git a/src/commands/clone/index.ts b/src/commands/clone/index.ts index 63b0bb7..9621958 100644 --- a/src/commands/clone/index.ts +++ b/src/commands/clone/index.ts @@ -3,9 +3,7 @@ import { Command } from 'commander'; import { projectConfig, projectEnvVars } from '../../config/project'; import Git from '../../utils/git'; import log from '../../utils/log'; -import sharedOptions, { - exitCommandIfInfoOnly, -} from '../../utils/shared-options'; +import sharedOptions from '../../utils/shared-options'; export const cloneCommand = () => { const command = new Command(); @@ -21,14 +19,16 @@ export const cloneCommand = () => { .addOption(sharedOptions.gitRef().default(config.git.default_ref)) .addOption(sharedOptions.reposRoot().default(config.paths.repos_root)) .addOption(sharedOptions.gitOrg().default(config.git.org_url)) + .addOption(sharedOptions.repos()) .addOption(sharedOptions.info()) .action((options) => { - console.log(`Git org > ${chalk.bold(options.gitOrg)}`); - console.log(`Git ref > ${chalk.bold(options.gitRef)}`); - console.log(`Repos path > ${chalk.bold(options.reposRoot)}`); - exitCommandIfInfoOnly(options.info); + console.log(`Git org > ${options.gitOrg}`); + console.log(`Git ref > ${options.gitRef}`); + console.log(`Repos path > ${options.reposRoot}`); - for (const repo of config.repositories) { + if (options.info) return; + + for (const repo of options.repos) { const repoUrl = `${options.gitOrg}/${repo}`; const git = new Git({ workingDir: options.reposRoot, diff --git a/src/commands/setup/index.ts b/src/commands/setup/index.ts index 9af267e..36ec71e 100644 --- a/src/commands/setup/index.ts +++ b/src/commands/setup/index.ts @@ -30,9 +30,9 @@ export const setupCommand = () => { ) .option('-p, --project-name [project-name]', 'Set project name') .option('-o, --repos-root-path [root-path]', 'Repositories root path') - .option('-r, --repo [repo...]', 'Set project repositories') .option('-e, --dot-env [path]', 'Project config dot env file') .option('-d, --dockerfile [dockerfile]', 'Dockerfile needed for dev') + .addOption(sharedOptions.repos()) .addOption(sharedOptions.gitOrg()) .addOption(sharedOptions.reposRoot()) .addOption(sharedOptions.gitRef()) @@ -82,7 +82,7 @@ export const setupCommand = () => { const repos = await input({ message: 'What are the repositories for this project? (comma-sperated list)', - default: demsEnvVars.repos || options.repo || 'demo-api,demo-webapp', + default: demsEnvVars.repos || options.repos || 'demo-api,demo-webapp', }); for (const repo of repos.split(',')) { config.repositories.push(repo); diff --git a/src/utils/file-system.ts b/src/utils/file-system.ts index 1d78670..dffe471 100644 --- a/src/utils/file-system.ts +++ b/src/utils/file-system.ts @@ -70,12 +70,15 @@ export const createPath = (path: string, verbose = true): void => { export const deletePath = async ({ path, force = false, + verbose = true, }: { path: string; force?: boolean; + verbose?: boolean; }): Promise => { if (!isDirectory(path)) { - log.warning(`⏩ Path: ${path} is not a valid directory. Not removing.`); + if (verbose) + log.warning(`⏩ Path: ${path} is not a valid directory. Not removing.`); return; } @@ -84,8 +87,8 @@ export const deletePath = async ({ (await confirm({ message: `Delete path ${path} recursively?` })) ) { fs.rmSync(path, { recursive: true, force: true }); - log.success(`🗑️ Path: ${path} recursively deleted.`); + if (verbose) log.success(`🗑️ Path: ${path} recursively deleted.`); } else { - log.info('⏩ Skipping...'); + if (verbose) log.info('⏩ Skipping...'); } }; diff --git a/src/utils/git.ts b/src/utils/git.ts index ba3a24a..ac5c4e1 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -1,4 +1,5 @@ import fs from 'node:fs'; +import { createPath } from './file-system.js'; import log from './log.js'; type GitParams = { @@ -20,7 +21,7 @@ export default class Git { clone({ workingDir, repo, ref }: GitParams) { this.remoteRepoExists(repo); - + createPath(workingDir); if (this.localRepoExists(this.repoPath)) { log.warning(`Repo ${repo} already cloned.`); } else { diff --git a/src/utils/shared-options.ts b/src/utils/shared-options.ts index 63d4871..b61e072 100644 --- a/src/utils/shared-options.ts +++ b/src/utils/shared-options.ts @@ -25,10 +25,9 @@ export const sharedOptions = { 'Git organization URL for repositories', ); }, -}; - -export const exitCommandIfInfoOnly = (info = false) => { - if (info) process.exit(0); + repos() { + return new Option('-r, --repos [repos...]', 'Git repositories to clone'); + }, }; export default sharedOptions; diff --git a/test/commands/clone.test.ts b/test/commands/clone.test.ts index b39bd62..19c150f 100644 --- a/test/commands/clone.test.ts +++ b/test/commands/clone.test.ts @@ -1,20 +1,21 @@ import { describe, expect, test } from 'bun:test'; import { spawnSync } from 'bun'; import { projectConfig } from '../../src/config/project'; +import { deletePath } from '../../src/utils/file-system'; import { removeExtraSpaces } from '../../src/utils/string'; describe("Command: 'clone'", () => { const config = projectConfig(); test('Flags (repos-root, git-org, git-ref) parsed correctly', () => { - const reposPath = './repos'; const gitRef = 'custom-branch'; const gitOrgUrl = 'git@github.com/example'; + const reposRoot = './repos'; const result = spawnSync([ './cli.ts', 'clone', '--repos-root', - reposPath, + reposRoot, '--git-ref', gitRef, '--git-org', @@ -23,8 +24,26 @@ describe("Command: 'clone'", () => { ]); const output = removeExtraSpaces(result.stdout.toString()); - expect(output).toContain(`Repos path > ${reposPath}`); + expect(output).toContain(`Repos path > ${reposRoot}`); expect(output).toContain(`Git ref > ${gitRef}`); expect(output).toContain(`Git org > ${gitOrgUrl}`); }); + + test('Clones a repository', () => { + const reposRoot = './repos'; + const result = spawnSync([ + './cli.ts', + 'clone', + '--repos', + 'demo-api', + '--repos', + 'demo-webapp', + '--repos-root', + reposRoot, + ]); + + const out = result.stdout.toString(); + const err = result.stderr.toString(); + deletePath({ path: reposRoot, force: true, verbose: false }); + }); });