diff --git a/packages/create-payload-app/package.json b/packages/create-payload-app/package.json index b51293da60..8170d02899 100644 --- a/packages/create-payload-app/package.json +++ b/packages/create-payload-app/package.json @@ -55,6 +55,7 @@ "@types/esprima": "^4.0.6", "@types/fs-extra": "^9.0.12", "@types/jest": "^27.0.3", - "@types/node": "20.12.5" + "@types/node": "20.12.5", + "temp-dir": "2.0.0" } } diff --git a/packages/create-payload-app/src/lib/create-project.spec.ts b/packages/create-payload-app/src/lib/create-project.spec.ts index ba57302e07..d9a91a3d12 100644 --- a/packages/create-payload-app/src/lib/create-project.spec.ts +++ b/packages/create-payload-app/src/lib/create-project.spec.ts @@ -2,25 +2,22 @@ import fse from 'fs-extra' import path from 'path' import type { CliArgs, DbType, ProjectTemplate } from '../types.js' import { createProject } from './create-project.js' -import { fileURLToPath } from 'node:url' import { dbReplacements } from './packages.js' import { getValidTemplates } from './templates.js' import globby from 'globby' -const filename = fileURLToPath(import.meta.url) -const dirname = path.dirname(filename) +import tempDirectory from 'temp-dir' -const projectDir = path.resolve(dirname, './tmp') describe('createProject', () => { + let projectDir: string beforeAll(() => { console.log = jest.fn() }) beforeEach(() => { - if (fse.existsSync(projectDir)) { - fse.rmdirSync(projectDir, { recursive: true }) - } + projectDir = `${tempDirectory}/${Math.random().toString(36).substring(7)}` }) + afterEach(() => { if (fse.existsSync(projectDir)) { fse.rmSync(projectDir, { recursive: true }) @@ -100,6 +97,9 @@ describe('createProject', () => { const packageJsonPath = path.resolve(projectDir, 'package.json') const packageJson = fse.readJsonSync(packageJsonPath) + // Verify git was initialized + expect(fse.existsSync(path.resolve(projectDir, '.git'))).toBe(true) + // Should only have one db adapter expect( Object.keys(packageJson.dependencies).filter((n) => n.startsWith('@payloadcms/db-')), diff --git a/packages/create-payload-app/src/lib/create-project.ts b/packages/create-payload-app/src/lib/create-project.ts index 7114320c2b..73f82980c4 100644 --- a/packages/create-payload-app/src/lib/create-project.ts +++ b/packages/create-payload-app/src/lib/create-project.ts @@ -8,6 +8,7 @@ import path from 'path' import type { CliArgs, DbDetails, PackageManager, ProjectTemplate } from '../types.js' +import { tryInitRepoAndCommit } from '../utils/git.js' import { debug, error, warning } from '../utils/log.js' import { configurePayloadConfig } from './configure-payload-config.js' @@ -108,6 +109,10 @@ export async function createProject(args: { } else { spinner.stop('Dependency installation skipped') } + + if (!cliArgs['--no-git']) { + tryInitRepoAndCommit({ cwd: projectDir }) + } } export async function updatePackageJSON(args: { diff --git a/packages/create-payload-app/src/main.ts b/packages/create-payload-app/src/main.ts index f32e14f756..9067ae9a29 100644 --- a/packages/create-payload-app/src/main.ts +++ b/packages/create-payload-app/src/main.ts @@ -53,6 +53,9 @@ export class Main { '--use-pnpm': Boolean, '--use-yarn': Boolean, + // Other + '--no-git': Boolean, + // Flags '--beta': Boolean, '--debug': Boolean, diff --git a/packages/create-payload-app/src/types.ts b/packages/create-payload-app/src/types.ts index 7d7febde79..d981538026 100644 --- a/packages/create-payload-app/src/types.ts +++ b/packages/create-payload-app/src/types.ts @@ -12,6 +12,7 @@ export interface Args extends arg.Spec { '--local-template': StringConstructor '--name': StringConstructor '--no-deps': BooleanConstructor + '--no-git': BooleanConstructor '--secret': StringConstructor '--template': StringConstructor '--template-branch': StringConstructor diff --git a/packages/create-payload-app/src/utils/git.ts b/packages/create-payload-app/src/utils/git.ts new file mode 100644 index 0000000000..08b76b54d7 --- /dev/null +++ b/packages/create-payload-app/src/utils/git.ts @@ -0,0 +1,50 @@ +import type { ExecSyncOptions } from 'child_process' + +import { execSync } from 'child_process' + +import { warning } from './log.js' + +export function tryInitRepoAndCommit(args: { cwd: string }): void { + const execOpts: ExecSyncOptions = { cwd: args.cwd, stdio: 'ignore' } + try { + // Check if git is available + execSync('git -v', execOpts) + + // Do nothing if already in a git repo + if (isGitRepo(execOpts)) { + return + } + + // Initialize + execSync('git init', execOpts) + if (!ensureHasDefaultBranch(execOpts)) { + execSync('git checkout -b main', execOpts) + } + + // Add and commit files + execSync('git add -A', execOpts) + execSync('git commit -m "feat: initial commit"', execOpts) + } catch (_) { + warning('Failed to initialize git repository.') + } +} + +function isGitRepo(opts: ExecSyncOptions): boolean { + try { + execSync('git rev-parse --is-inside-work-tree', opts) + return true + } catch (_) { + // Ignore errors + } + return false +} + +function ensureHasDefaultBranch(opts: ExecSyncOptions): boolean { + try { + execSync(`git config init.defaultBranch`, opts) + return true + } catch (_) { + // Ignore errros + } + return false +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 114922ee5b..95e31783b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -328,6 +328,9 @@ importers: '@types/node': specifier: 20.12.5 version: 20.12.5 + temp-dir: + specifier: 2.0.0 + version: 2.0.0 packages/db-mongodb: dependencies: