From d97abb04e316c64fbc1b1de7fac5d9189b1c532e Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 17 Aug 2026 13:58:57 -0700 Subject: [PATCH] fix(deploy): restore shared-deployment namespace merge broken by src/__init__.py cockpit/langgraph/client-tools shipped an empty src/__init__.py (#642) that turned its src into a regular package; per PEP 420 that wins over every other dep's namespace portion, so c-interrupts' 'from src.aviation_tools import' raised ModuleNotFoundError at startup and every revision since Aug 7 hit DEPLOY_FAILED (production smoke timeouts were the wedged run queue). Delete the file and make the manifest generator throw if any staged dep reintroduces one. Co-Authored-By: Claude Fable 5 --- .../langgraph/client-tools/python/src/__init__.py | 1 - scripts/generate-shared-deployment-config.ts | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) delete mode 100644 cockpit/langgraph/client-tools/python/src/__init__.py diff --git a/cockpit/langgraph/client-tools/python/src/__init__.py b/cockpit/langgraph/client-tools/python/src/__init__.py deleted file mode 100644 index 548d2d447..000000000 --- a/cockpit/langgraph/client-tools/python/src/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# SPDX-License-Identifier: MIT diff --git a/scripts/generate-shared-deployment-config.ts b/scripts/generate-shared-deployment-config.ts index bde5285f4..ff9f4472f 100644 --- a/scripts/generate-shared-deployment-config.ts +++ b/scripts/generate-shared-deployment-config.ts @@ -1,4 +1,4 @@ -import { cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'; +import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'; import { dirname, resolve } from 'path'; import { capabilities } from '../apps/cockpit/scripts/capability-registry'; @@ -41,6 +41,19 @@ const stageDependency = (sourceRoot: string, alias: string): string => { const stagedDir = resolve(stagedDependenciesDir, alias); cpSync(sourceDir, stagedDir, { recursive: true }); + // Every dep ships a `src/` package and they must all merge as PEP 420 + // namespace portions on the deployment's sys.path. A single + // `src/__init__.py` turns that dep's `src` into a REGULAR package which + // wins exclusively, so every other dep's `from src.x import ...` raises + // ModuleNotFoundError at startup and the whole revision fails to deploy + // (this exact failure shipped in #642 and broke deploys from Aug 7). + const initPy = resolve(stagedDir, 'src/__init__.py'); + if (existsSync(initPy)) { + throw new Error( + `${sourceRoot}/src/__init__.py breaks the shared deployment's namespace-package merge — delete it (deps' src dirs must be namespace packages)`, + ); + } + const relativePath = `./deps/${alias}`; stagedDependencyRoots.set(sourceRoot, relativePath); dependencies.add(relativePath);