Skip to content

Commit 3885140

Browse files
committed
fix(docker): auto-detect non-interactive environments (Docker, CI, no-TTY)
- Add comprehensive detection for Docker containers (/.dockerenv, /run/.containerenv) - Add TTY detection via sys.stdin.isatty() for piped input - Add OMNIPKG_NONINTERACTIVE env var for explicit override - Keep existing CI env var detection - Non-interactive mode now uses all defaults, no input() prompts - Fixes EOFError crashes in Docker/CI environments - Resolves #(issue) if applicable
1 parent 52c9d66 commit 3885140

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

src/omnipkg/core.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,26 @@ def _first_time_setup(self, interactive=True) -> Dict:
24512451
"""
24522452
Interactive setup that keeps the native Python in its original location
24532453
and only manages additional Python versions.
2454-
"""
2454+
2455+
AUTO-DETECTS non-interactive environments (Docker, CI, piped input, etc.)
2456+
"""
2457+
import sys
2458+
2459+
# ============================================================================
2460+
# CRITICAL: Auto-detect non-interactive environments
2461+
# ============================================================================
2462+
is_docker = os.path.exists("/.dockerenv") or os.path.exists("/run/.containerenv")
2463+
no_tty = not sys.stdin.isatty()
2464+
forced_noninteractive = os.environ.get("OMNIPKG_NONINTERACTIVE")
2465+
in_ci = os.environ.get("CI")
2466+
2467+
# If ANY of these conditions are true, force non-interactive mode
2468+
if interactive and (in_ci or forced_noninteractive or no_tty or is_docker):
2469+
interactive = False
2470+
safe_print(_("🤖 Non-interactive environment detected - using defaults"))
2471+
2472+
# ============================================================================
2473+
24552474
safe_print(_("💡 Grounding configuration in the current active environment..."))
24562475

24572476
# Use the ACTUAL active Python executable, not a managed copy
@@ -2606,8 +2625,8 @@ def _first_time_setup(self, interactive=True) -> Dict:
26062625
defaults = self._get_sensible_defaults(managed_python_exe_str)
26072626
final_config = defaults.copy()
26082627

2609-
# Interactive prompts (if not in CI)
2610-
if interactive and (not os.environ.get("CI")):
2628+
# Interactive prompts (ONLY if truly interactive)
2629+
if interactive:
26112630
safe_print(_("🌍 Welcome to omnipkg! Let's get you configured."))
26122631
safe_print("-" * 60)
26132632

@@ -2678,6 +2697,9 @@ def _first_time_setup(self, interactive=True) -> Dict:
26782697
input(_("Enable Python interpreter hotswapping? (y/n) [y]: ")).strip().lower()
26792698
)
26802699
final_config["enable_python_hotswap"] = hotswap_choice != "n"
2700+
else:
2701+
# Non-interactive: use all defaults
2702+
safe_print(_(" ✅ Using default configuration (non-interactive mode)"))
26812703

26822704
# Save configuration
26832705
try:
@@ -2694,7 +2716,7 @@ def _first_time_setup(self, interactive=True) -> Dict:
26942716
with open(self.config_path, "w") as f:
26952717
json.dump(full_config, f, indent=4)
26962718

2697-
if interactive and (not os.environ.get("CI")):
2719+
if interactive:
26982720
safe_print(_("\n✅ Configuration saved to {}.").format(self.config_path))
26992721
safe_print(_(" You can edit this file manually later."))
27002722
safe_print(_("🧠 Initializing omnipkg knowledge base..."))
@@ -2710,7 +2732,7 @@ def _first_time_setup(self, interactive=True) -> Dict:
27102732
"-y",
27112733
]
27122734
try:
2713-
if interactive and (not os.environ.get("CI")):
2735+
if interactive:
27142736
process = subprocess.Popen(
27152737
rebuild_cmd,
27162738
stdout=subprocess.PIPE,
@@ -2735,7 +2757,7 @@ def _first_time_setup(self, interactive=True) -> Dict:
27352757
else:
27362758
subprocess.run(rebuild_cmd, check=True, capture_output=True, text=True)
27372759
except subprocess.CalledProcessError:
2738-
if interactive and (not os.environ.get("CI")):
2760+
if interactive:
27392761
safe_print(_(" ⚠️ Knowledge base will be built on first command usage instead."))
27402762
pass
27412763

0 commit comments

Comments
 (0)