Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .claude/settings.local.json

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ requirements-mxdev.txt
.venv/
dist/
src/mxdev/_version.py
.claude
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 5.0.1 (unreleased)

- Fix #65: Check source directories exist before writing to requirements-mxdev.txt. In **offline mode**: missing sources log WARNING and are written as comments (expected behavior). In **non-offline mode**: missing sources log ERROR and mxdev exits with RuntimeError (fatal error indicating checkout failure). This fixes mxmake two-stage installation workflow and prevents silent failures when sources fail to check out.
[jensens]
- Fix: Add 'synchronize' event to pull_request workflow triggers. This ensures CI runs when PRs are updated with new commits (e.g., after rebasing or pushing new changes), not just when opened or reopened.
[jensens]
- Chore: Optimize GitHub Actions to prevent duplicate workflow runs on pull requests. Restrict `push` trigger to only run on `main` branch, so PRs only trigger via `pull_request` event. This reduces CI resource usage by 50% for PR workflows.
Expand Down
54 changes: 49 additions & 5 deletions src/mxdev/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,26 +210,70 @@ def fetch(state: State) -> None:
)


def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]]):
def write_dev_sources(fio, packages: dict[str, dict[str, typing.Any]], state: State):
"""Create requirements configuration for fetched source packages."""
if not packages:
return

# Check if we're in offline mode or no-fetch mode
from .config import to_bool

offline_mode = to_bool(state.configuration.settings.get("offline", False))
missing_sources = [] # Track missing sources for error handling

fio.write("#" * 79 + "\n")
fio.write("# mxdev development sources\n")

for name, package in packages.items():
if package["install-mode"] == "skip":
continue

# Check if source directory exists
source_path = Path(package["path"])

extras = f"[{package['extras']}]" if package["extras"] else ""
subdir = f"/{package['subdirectory']}" if package["subdirectory"] else ""

# Add -e prefix only for 'editable' mode (not for 'fixed')
prefix = "-e " if package["install-mode"] == "editable" else ""
install_line = f"""{prefix}./{package['target']}/{name}{subdir}{extras}\n"""
install_line = f"""{prefix}./{package['target']}/{name}{subdir}{extras}"""

if not source_path.exists():
# Source not checked out yet - write as comment
missing_sources.append(name)

if offline_mode:
# In offline mode, missing sources are expected - log as WARNING
reason = (
f"Source directory does not exist: {source_path} (package: {name}). "
f"This is expected in offline mode. Run mxdev without -n and --offline flags to fetch sources."
)
logger.warning(reason)
else:
# In non-offline mode, missing sources are a fatal error - log as ERROR
reason = (
f"Source directory does not exist: {source_path} (package: {name}). "
f"This indicates a failure in the checkout process. "
f"Run mxdev without -n flag to fetch sources."
)
logger.error(reason)

fio.write(f"# {install_line} # mxdev: source not checked out\n")
else:
# Source exists - write normally
logger.debug(f"-> {install_line}")
fio.write(f"{install_line}\n")

logger.debug(f"-> {install_line.strip()}")
fio.write(install_line)
fio.write("\n\n")

# In non-offline mode, missing sources are a fatal error
if not offline_mode and missing_sources:
raise RuntimeError(
f"Source directories missing for packages: {', '.join(missing_sources)}. "
f"This indicates a failure in the checkout process. "
f"Run mxdev without -n flag to fetch sources."
)


def write_dev_overrides(fio, overrides: dict[str, str], package_keys: list[str]):
"""Create requirements configuration for overridden packages."""
Expand Down Expand Up @@ -292,6 +336,6 @@ def write(state: State) -> None:
fio.write("#" * 79 + "\n")
fio.write("# mxdev combined constraints\n")
fio.write(f"-c {constraints_ref}\n\n")
write_dev_sources(fio, cfg.packages)
write_dev_sources(fio, cfg.packages, state)
fio.writelines(requirements)
write_main_package(fio, cfg.settings)
Loading