From 4f4e493c02991270fbe62f8bc4fc0af288cb2212 Mon Sep 17 00:00:00 2001 From: hoyeon Date: Wed, 28 Oct 2026 22:29:13 +0900 Subject: [PATCH] fix: remove script config deprecation warning --- .../remove-config-deprecation-warning.md | 5 ++++ README.md | 4 +-- src/core/config/resolve-config.spec.ts | 26 +++++-------------- src/core/config/resolve-config.ts | 15 ----------- tests/codeowners-cli.spec.ts | 22 ++++------------ tests/config-cli.spec.ts | 23 +++++----------- tests/output-read-errors.spec.ts | 24 +++-------------- 7 files changed, 28 insertions(+), 91 deletions(-) create mode 100644 .changeset/remove-config-deprecation-warning.md diff --git a/.changeset/remove-config-deprecation-warning.md b/.changeset/remove-config-deprecation-warning.md new file mode 100644 index 0000000..167433d --- /dev/null +++ b/.changeset/remove-config-deprecation-warning.md @@ -0,0 +1,5 @@ +--- +'@pull-up/cli': patch +--- + +Remove the deprecation warning for JavaScript and TypeScript configuration files. diff --git a/README.md b/README.md index 5db4e42..3d62d4a 100644 --- a/README.md +++ b/README.md @@ -134,9 +134,7 @@ The path is relative to the YAML file. For Yarn Plug'n'Play or a remote schema, ### JavaScript and TypeScript Configuration -Starting in 0.0.8, JavaScript and TypeScript configuration files are deprecated. They continue to work, but pull-up prints one warning to stderr per command when it loads a `.js`, `.ts`, `.cjs`, or `.mjs` configuration file, including `.pulluprc` files with these extensions. See [Migration](#migration) to move to YAML. - -The `package.json` `pullup` field and JSON/YAML `.pulluprc` configurations remain supported without this deprecation warning. +JavaScript and TypeScript configuration files are supported alongside YAML configuration. Use `pullup.config.ts`, `pullup.config.js`, `pullup.config.cjs`, or `pullup.config.mjs` for a JavaScript or TypeScript configuration: diff --git a/src/core/config/resolve-config.spec.ts b/src/core/config/resolve-config.spec.ts index 6dbace2..c4d2a03 100644 --- a/src/core/config/resolve-config.spec.ts +++ b/src/core/config/resolve-config.spec.ts @@ -1,5 +1,3 @@ -import path from 'node:path'; - import { Fixture } from '@fixture-kit/core'; import { resolveConfig } from './resolve-config'; @@ -90,19 +88,14 @@ describe('resolveConfig', () => { ['.pulluprc.ts', tsConfig], ['.pulluprc.cjs', cjsConfig], ['.pulluprc.mjs', esmConfig], - ])('resolves jobs from %s and warns about deprecation once', async (filename, contents) => { + ])('resolves jobs from %s without a deprecation warning', async (filename, contents) => { await using fixture = await Fixture.create({ 'package.json': JSON.stringify({ type: 'module' }), [filename]: contents, }); expect(await resolveConfig(fixture.root)).toEqual(customJobs); - expect(console.warn).toHaveBeenCalledOnce(); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining(path.join(fixture.root, filename))); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('[DEPRECATED]')); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('pullup.yml or pullup.yaml')); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('external commands')); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('https://github.com/toss/pull-up#migration')); + expect(console.warn).not.toHaveBeenCalled(); }); it.each([ @@ -120,22 +113,18 @@ describe('resolveConfig', () => { expect(console.warn).not.toHaveBeenCalled(); }); - it('warns about an empty JavaScript configuration', async () => { + it('resolves an empty JavaScript configuration without a deprecation warning', async () => { await using fixture = await Fixture.create({ 'pullup.config.cjs': 'module.exports = [];' }); expect(await resolveConfig(fixture.root)).toEqual([]); - expect(console.warn).toHaveBeenCalledOnce(); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining(path.join(fixture.root, 'pullup.config.cjs'))); + expect(console.warn).not.toHaveBeenCalled(); }); - it('warns about a script configuration discovered inside .config', async () => { + it('resolves a script configuration inside .config without a deprecation warning', async () => { await using fixture = await Fixture.create({ '.config': { 'pulluprc.cjs': cjsConfig } }); expect(await resolveConfig(fixture.root)).toEqual(customJobs); - expect(console.warn).toHaveBeenCalledOnce(); - expect(console.warn).toHaveBeenCalledWith( - expect.stringContaining(path.join(fixture.root, '.config', 'pulluprc.cjs')), - ); + expect(console.warn).not.toHaveBeenCalled(); }); it('resolves jobs from package.json#pullup', async () => { @@ -175,8 +164,7 @@ describe('resolveConfig', () => { 'pullup.yml': 'jobs: []\n', }); expect(await resolveConfig(fixture.root)).toEqual(customJobs); - expect(console.warn).toHaveBeenCalledOnce(); - expect(console.warn).toHaveBeenCalledWith(expect.stringContaining(path.join(fixture.root, 'pullup.config.js'))); + expect(console.warn).not.toHaveBeenCalled(); }); it('prefers package.json over pullup.config.js', async () => { diff --git a/src/core/config/resolve-config.ts b/src/core/config/resolve-config.ts index a78f714..0d2fda2 100644 --- a/src/core/config/resolve-config.ts +++ b/src/core/config/resolve-config.ts @@ -1,5 +1,4 @@ import path from 'node:path'; -import { styleText } from 'node:util'; import { cosmiconfig, getDefaultSearchPlaces } from 'cosmiconfig'; import * as v from 'valibot'; @@ -23,20 +22,6 @@ export async function resolveConfig(cwd: string): Promise { return toJobs(v.parse(ConfigSchema, result.config)); } - if (['.js', '.ts', '.cjs', '.mjs'].includes(path.extname(result.filepath))) { - console.warn( - styleText( - 'yellow', - [ - `[DEPRECATED] JavaScript/TypeScript configuration is deprecated: ${result.filepath}`, - 'Use pullup.yml or pullup.yaml for built-in jobs and external commands for custom transforms.', - 'Migration guide: https://github.com/toss/pull-up#migration', - '', - ].join('\n'), - ), - ); - } - return result.config as Job[]; } diff --git a/tests/codeowners-cli.spec.ts b/tests/codeowners-cli.spec.ts index cb1f047..78f17c8 100644 --- a/tests/codeowners-cli.spec.ts +++ b/tests/codeowners-cli.spec.ts @@ -13,16 +13,6 @@ const config = `import { codeownersJob } from ${JSON.stringify(CORE_URL)}; export default [codeownersJob()]; `; -function expectScriptConfigWarning(result: { stdout: string; stderr: string }, configPath: string) { - expect(result.stderr).toBe( - `[DEPRECATED] JavaScript/TypeScript configuration is deprecated: ${configPath}\n` + - 'Use pullup.yml or pullup.yaml for built-in jobs and external commands for custom transforms.\n' + - 'Migration guide: https://github.com/toss/pull-up#migration\n\n', - ); - expect(result.stderr.match(/\[DEPRECATED\]/g)).toHaveLength(1); - expect(result.stdout).not.toContain('[DEPRECATED]'); -} - describe('codeowners-cli', () => { it.each([ { name: 'the repository root', cwd: 'repo', explicitRoot: false }, @@ -55,15 +45,13 @@ describe('codeowners-cli', () => { const options: string[] = []; if (scenario.explicitRoot) options.push('--root', rootDir); if (scenario.explicitCwd === true) options.push('--cwd', subdirectory); - const configDirectory = scenario.explicitCwd === true ? subdirectory : path.join(fixture.root, scenario.cwd); - const configPath = path.join(configDirectory, 'pullup.config.mjs'); const sync = await execFileAsync(process.execPath, [CLI_PATH, 'sync', ...options], { cwd: path.join(fixture.root, scenario.cwd), timeout: 10_000, }); expect(sync.stdout).toContain('codeowners synced'); - expectScriptConfigWarning(sync, configPath); + expect(sync.stderr).toBe(''); expect(await readFile(path.join(rootDir, '.github/CODEOWNERS'), 'utf8')).toBe( '* @root-team\n' + @@ -85,7 +73,7 @@ describe('codeowners-cli', () => { timeout: 10_000, }); expect(check.stdout).toContain('All files are up to date'); - expectScriptConfigWarning(check, configPath); + expect(check.stderr).toBe(''); if (scenario.explicitRoot || scenario.explicitCwd === true) { await expect(readFile(path.join(otherRoot, '.github/CODEOWNERS'), 'utf8')).rejects.toMatchObject({ @@ -117,7 +105,7 @@ export default [codeownersJob({ input: ${JSON.stringify(scenario.input)} })]; timeout: 10_000, }); - expectScriptConfigWarning(sync, path.join(rootDir, 'pullup.config.mjs')); + expect(sync.stderr).toBe(''); expect(await readFile(path.join(rootDir, '.github/CODEOWNERS'), 'utf8')).toBe( '/services/auth/ @auth-team\n' + '/services/auth/login/ @login-team\n', ); @@ -138,7 +126,7 @@ export default [codeownersJob({ input: ${JSON.stringify(scenario.input)} })]; const sync = await execFileAsync(process.execPath, [CLI_PATH, 'sync'], { cwd: fixture.root, timeout: 10_000 }); expect(sync.stdout).toContain('codeowners synced'); - expectScriptConfigWarning(sync, path.join(fixture.root, 'pullup.config.mjs')); + expect(sync.stderr).toBe(''); expect(await readFile(path.join(fixture.root, '.github/CODEOWNERS'), 'utf8')).toBe( '*.js @root-team\n' + '/packages/web/**/*.ts @frontend-team\n' + @@ -150,6 +138,6 @@ export default [codeownersJob({ input: ${JSON.stringify(scenario.input)} })]; const check = await execFileAsync(process.execPath, [CLI_PATH, 'check'], { cwd: fixture.root, timeout: 10_000 }); expect(check.stdout).toContain('All files are up to date'); - expectScriptConfigWarning(check, path.join(fixture.root, 'pullup.config.mjs')); + expect(check.stderr).toBe(''); }); }); diff --git a/tests/config-cli.spec.ts b/tests/config-cli.spec.ts index 0144574..70c6e07 100644 --- a/tests/config-cli.spec.ts +++ b/tests/config-cli.spec.ts @@ -23,14 +23,6 @@ const config = `jobs: output: .github/CODEOWNERS `; -function scriptConfigWarning(configPath: string) { - return ( - `[DEPRECATED] JavaScript/TypeScript configuration is deprecated: ${configPath}\n` + - 'Use pullup.yml or pullup.yaml for built-in jobs and external commands for custom transforms.\n' + - 'Migration guide: https://github.com/toss/pull-up#migration\n\n' - ); -} - function runCli(command: string, rootDir: string, args: string[] = []) { return execFileAsync(process.execPath, [CLI_PATH, command, ...args], { cwd: rootDir, @@ -145,8 +137,7 @@ describe('YAML config CLI', () => { const result = await runCli(command, fixture.root); expect(result.code).toBe(0); - expect(result.stderr).toBe(scriptConfigWarning(path.join(fixture.root, 'pullup.config.mjs'))); - expect(result.stderr.match(/\[DEPRECATED\]/g)).toHaveLength(1); + expect(result.stderr).toBe(''); expect(result.stdout).not.toContain('[DEPRECATED]'); expect(result.stdout).toContain(command === 'sync' ? 'custom synced' : 'All files are up to date'); expect(await readFile(path.join(fixture.root, '.github/CODEOWNERS'), 'utf8')).toBe(generatedContents); @@ -154,8 +145,8 @@ describe('YAML config CLI', () => { }); }); -describe('script config CLI deprecation warning', () => { - it('warns once for sync --dry-run while preserving the preview and existing output', async () => { +describe('script config CLI', () => { + it('previews sync --dry-run without warnings or changing the existing output', async () => { await using fixture = await Fixture.create({ '.git': {}, 'pullup.config.mjs': scriptConfig, @@ -165,8 +156,7 @@ describe('script config CLI deprecation warning', () => { const result = await runCli('sync', fixture.root, ['--dry-run']); expect(result.code).toBe(0); - expect(result.stderr).toBe(scriptConfigWarning(path.join(fixture.root, 'pullup.config.mjs'))); - expect(result.stderr.match(/\[DEPRECATED\]/g)).toHaveLength(1); + expect(result.stderr).toBe(''); expect(result.stdout).not.toContain('[DEPRECATED]'); expect(result.stdout).toContain('[Job] custom'); expect(result.stdout).toContain('Output: .github/CODEOWNERS'); @@ -174,7 +164,7 @@ describe('script config CLI deprecation warning', () => { expect(await readFile(path.join(fixture.root, '.github/CODEOWNERS'), 'utf8')).toBe(existingContents); }); - it('warns once without changing the outdated check failure or existing output', async () => { + it('reports an outdated check failure without deprecation warnings or changing the existing output', async () => { await using fixture = await Fixture.create({ '.git': {}, 'pullup.config.mjs': scriptConfig, @@ -184,8 +174,7 @@ describe('script config CLI deprecation warning', () => { const result = await runCli('check', fixture.root); expect(result.code).toBe(1); - expect(result.stderr).toContain(scriptConfigWarning(path.join(fixture.root, 'pullup.config.mjs'))); - expect(result.stderr.match(/\[DEPRECATED\]/g)).toHaveLength(1); + expect(result.stderr).not.toContain('[DEPRECATED]'); expect(result.stderr).toContain("custom is outdated. Run 'pullup sync' to update."); expect(result.stdout).toBe(''); expect(await readFile(path.join(fixture.root, '.github/CODEOWNERS'), 'utf8')).toBe(existingContents); diff --git a/tests/output-read-errors.spec.ts b/tests/output-read-errors.spec.ts index 8899363..a9896ce 100644 --- a/tests/output-read-errors.spec.ts +++ b/tests/output-read-errors.spec.ts @@ -17,20 +17,6 @@ const config = `export default [ ]; `; -function scriptConfigWarning(rootDir: string) { - return ( - `[DEPRECATED] JavaScript/TypeScript configuration is deprecated: ${path.join(rootDir, 'pullup.config.mjs')}\n` + - 'Use pullup.yml or pullup.yaml for built-in jobs and external commands for custom transforms.\n' + - 'Migration guide: https://github.com/toss/pull-up#migration\n\n' - ); -} - -function expectScriptConfigWarning(result: { stdout: string; stderr: string }, rootDir: string) { - expect(result.stderr).toContain(scriptConfigWarning(rootDir)); - expect(result.stderr.match(/\[DEPRECATED\]/g)).toHaveLength(1); - expect(result.stdout).not.toContain('[DEPRECATED]'); -} - async function prepareRepository(rootDir: string) { await mkdir(path.join(rootDir, '.git')); await mkdir(path.join(rootDir, '.github'), { recursive: true }); @@ -58,7 +44,7 @@ describe('output read errors', () => { const result = await runCli(command, fixture.root); expect(result.code).toBe(1); - expectScriptConfigWarning(result, fixture.root); + expect(result.stdout + result.stderr).not.toContain('[DEPRECATED]'); expect(result.stdout + result.stderr).toContain('EISDIR'); expect(result.stdout + result.stderr).toContain(outputPath); expect(result.stdout + result.stderr).not.toContain('outdated'); @@ -81,7 +67,7 @@ describe('output read errors', () => { const result = await runCli(command, fixture.root); expect(result.code).toBe(1); - expectScriptConfigWarning(result, fixture.root); + expect(result.stdout + result.stderr).not.toContain('[DEPRECATED]'); expect(result.stdout + result.stderr).toContain('EACCES'); expect(result.stdout + result.stderr).toContain(outputPath); expect(result.stdout + result.stderr).not.toContain('outdated'); @@ -103,16 +89,14 @@ describe('output read errors', () => { const sync = await runCli('sync', fixture.root); expect(sync.code).toBe(0); - expect(sync.stderr).toBe(scriptConfigWarning(fixture.root)); - expectScriptConfigWarning(sync, fixture.root); + expect(sync.stderr).toBe(''); expect(sync.stdout).toContain('unreadable synced'); expect(await readFile(path.join(fixture.root, output), 'utf8')).toBe('generated output\n'); const check = await runCli('check', fixture.root); expect(check.code).toBe(0); - expect(check.stderr).toBe(scriptConfigWarning(fixture.root)); - expectScriptConfigWarning(check, fixture.root); + expect(check.stderr).toBe(''); expect(check.stdout).toContain('All files are up to date'); }); });