diff --git a/src/commands/run.ts b/src/commands/run.ts index 917f9593f..f089b8c4e 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -420,7 +420,9 @@ export class RunCommand extends ApifyCommand { } /** - * Ensures the input that the actor will be ran with locally matches the input schema (and prefills default values if missing) + * Validates the input against the input schema and writes to disk only when necessary. + * When the user already has an INPUT.json and no override is provided, it validates in-memory + * without modifying the file (returns null so the finally block is a no-op). * @param inputOverride Optional input received through command flags */ private async validateAndStoreInput(inputOverride?: { input: Record; source: string }) { @@ -546,15 +548,8 @@ export class RunCommand extends ApifyCommand { ); } - // Step 4: store the input - await mkdir(dirname(inputFilePath), { recursive: true }); - await writeFile(inputFilePath, JSON.stringify(fullInput, null, 2)); - - return { - existingInput, - inputFilePath, - writtenAt: Date.now(), - }; + // Don't write to the file — leave the user's INPUT.json untouched + return null; } return null; diff --git a/test/local/commands/crawlee/run.test.ts b/test/local/commands/crawlee/run.test.ts index 6d06d891b..69174d587 100644 --- a/test/local/commands/crawlee/run.test.ts +++ b/test/local/commands/crawlee/run.test.ts @@ -68,22 +68,25 @@ describe('apify run', () => { expect(lastErrorMessage()).toMatch(/Field awesome is required/i); }); - it('prefills input with defaults', async () => { + it('validates input without modifying file', async () => { await writeFile(inputPath, originalInput); await testRunCommand(RunCommand, {}); const output = JSON.parse(await readFile(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you' }); + + const inputAfterRun = await readFile(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalInput); }); - it('should restore the original input file after run', async () => { + it('does not modify input file during run', async () => { await writeFile(inputPath, originalInputWithExtraField); await testRunCommand(RunCommand, {}); - const input = JSON.parse(await readFile(inputPath, 'utf8')); - expect(input).toStrictEqual({ awesome: true, extra: 'field' }); + const inputAfterRun = await readFile(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalInputWithExtraField); const output = JSON.parse(await readFile(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you', extra: 'field' }); diff --git a/test/local/commands/run.test.ts b/test/local/commands/run.test.ts index dbbf6fc9b..547b0451e 100644 --- a/test/local/commands/run.test.ts +++ b/test/local/commands/run.test.ts @@ -333,14 +333,18 @@ writeFileSync(String.raw\`${joinPath('result.txt')}\`, 'hello world'); expect(lastErrorMessage()).toMatch(/Field help must be string/i); }); - it('automatically inserts missing defaulted fields', async () => { - writeFileSync(inputPath, '{"awesome": true}', { flag: 'w' }); + it('does not inject defaults into existing input file', async () => { + const originalContent = '{"awesome": true}'; + writeFileSync(inputPath, originalContent, { flag: 'w' }); copyFileSync(defaultsInputSchemaPath, inputSchemaPath); await testRunCommand(RunCommand, {}); const output = JSON.parse(readFileSync(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you' }); + + const inputAfterRun = readFileSync(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalContent); }); it('does not insert missing prefilled fields', async () => {