From c23d6567f0b6e1c624a9a7d01882517eda278f4a Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Fri, 16 Oct 2026 11:52:23 -0700 Subject: [PATCH 1/2] feat(init): warn when a Python project has no Dockerfile --- src/commands/init.ts | 16 +++++++++++++++- test/local/commands/init.test.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 87f02ceb0..6f9cbd1ef 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -1,4 +1,5 @@ -import { basename } from 'node:path'; +import { existsSync } from 'node:fs'; +import { basename, join } from 'node:path'; import process from 'node:process'; import { ApifyCommand } from '../lib/command-framework/apify-command.js'; @@ -163,6 +164,19 @@ export class InitCommand extends ApifyCommand { await setLocalConfig(configToWrite, cwd); } + if ( + project.type === ProjectLanguage.Python && + !this.flags.dockerfile && + !actorConfig.unwrapOr(undefined)?.config.dockerfile && + !existsSync(join(cwd, '.actor', 'Dockerfile')) && + !existsSync(join(cwd, 'Dockerfile')) + ) { + warning({ + message: + 'No Dockerfile found. Without one, the Apify platform builds the Actor with a Node.js base image. Add one at .actor/Dockerfile (e.g. FROM apify/actor-python) or pass --dockerfile.', + }); + } + await setLocalEnv(cwd); // Create prefilled INPUT.json file from the input schema prefills diff --git a/test/local/commands/init.test.ts b/test/local/commands/init.test.ts index 782ef874e..cac0d7e48 100644 --- a/test/local/commands/init.test.ts +++ b/test/local/commands/init.test.ts @@ -6,7 +6,9 @@ import { KEY_VALUE_STORE_KEYS } from '@apify/consts'; import { testRunCommand } from '../../../src/lib/command-framework/apify-command.js'; import { EMPTY_LOCAL_CONFIG, LOCAL_CONFIG_PATH } from '../../../src/lib/consts.js'; import { getLocalKeyValueStorePath } from '../../../src/lib/utils.js'; +import { useConsoleSpy } from '../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../__setup__/hooks/useTempPath.js'; +import { resetCwdCaches } from '../../__setup__/reset-cwd-caches.js'; const actName = 'init-my-actor'; const { beforeAllCalls, afterAllCalls, joinPath } = useTempPath(actName, { @@ -16,11 +18,14 @@ const { beforeAllCalls, afterAllCalls, joinPath } = useTempPath(actName, { cwdParent: false, }); +const { logMessages } = useConsoleSpy(); + const { InitCommand } = await import('../../../src/commands/init.js'); describe('apify init', () => { beforeEach(async () => { await beforeAllCalls(); + resetCwdCaches(); }); afterEach(async () => { @@ -120,4 +125,25 @@ describe('apify init', () => { expect(config).toStrictEqual(Object.assign(EMPTY_LOCAL_CONFIG, { name: actName })); expect(config.dockerfile).toBeUndefined(); }); + + it('warns when a Python project has no Dockerfile', async () => { + await mkdir(joinPath('my_actor'), { recursive: true }); + writeFileSync(joinPath('my_actor', '__init__.py'), ''); + writeFileSync(joinPath('my_actor', '__main__.py'), ''); + + await testRunCommand(InitCommand, { args_actorName: actName, flags_yes: true }); + + expect(logMessages.error.join('\n')).toMatch(/No Dockerfile found/); + }); + + it('does not warn when a Python project has a Dockerfile', async () => { + await mkdir(joinPath('my_actor'), { recursive: true }); + writeFileSync(joinPath('my_actor', '__init__.py'), ''); + writeFileSync(joinPath('my_actor', '__main__.py'), ''); + writeFileSync(joinPath('Dockerfile'), 'FROM apify/actor-python'); + + await testRunCommand(InitCommand, { args_actorName: actName, flags_yes: true }); + + expect(logMessages.error.join('\n')).not.toMatch(/No Dockerfile found/); + }); }); From 3fb2c62f563ee28d390757542f527ae83005ace7 Mon Sep 17 00:00:00 2001 From: patrikbraborec Date: Fri, 16 Oct 2026 12:01:42 -0700 Subject: [PATCH 2/2] refactor(init): name the Dockerfile warning condition --- src/commands/init.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 6f9cbd1ef..23e99cadd 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -164,13 +164,14 @@ export class InitCommand extends ApifyCommand { await setLocalConfig(configToWrite, cwd); } - if ( + const isPythonWithoutDockerfile = project.type === ProjectLanguage.Python && !this.flags.dockerfile && !actorConfig.unwrapOr(undefined)?.config.dockerfile && !existsSync(join(cwd, '.actor', 'Dockerfile')) && - !existsSync(join(cwd, 'Dockerfile')) - ) { + !existsSync(join(cwd, 'Dockerfile')); + + if (isPythonWithoutDockerfile) { warning({ message: 'No Dockerfile found. Without one, the Apify platform builds the Actor with a Node.js base image. Add one at .actor/Dockerfile (e.g. FROM apify/actor-python) or pass --dockerfile.',