diff --git a/changelog.d/20250226_134324_ahmed.khalid_mfe_ports_bug.md b/changelog.d/20250226_134324_ahmed.khalid_mfe_ports_bug.md new file mode 100644 index 00000000..8ff1cfdf --- /dev/null +++ b/changelog.d/20250226_134324_ahmed.khalid_mfe_ports_bug.md @@ -0,0 +1 @@ +- [Bugfix] Fixed syntax error in Docker configuration when all MFEs are mounted by ensuring the `ports:` section is only included if unmounted MFEs exist. (by @ahmed-arb and @hinakhadim) diff --git a/tutormfe/patches/local-docker-compose-dev-services b/tutormfe/patches/local-docker-compose-dev-services index 4d952e50..e816824d 100644 --- a/tutormfe/patches/local-docker-compose-dev-services +++ b/tutormfe/patches/local-docker-compose-dev-services @@ -1,14 +1,6 @@ -mfe: - ports: - {%- for app_name, app in iter_mfes() %} - {%- if not iter_mounts(MOUNTS, app_name)|list %} - - {{ app["port"] }}:8002 # {{ app_name }} - {%- endif %} - {%- endfor %} +{%- set mfe_data = MFEMountData(MOUNTS) %} -{%- for app_name, app in iter_mfes() %} -{%- set mounts = iter_mounts(MOUNTS, app_name)|list %} -{%- if mounts %} +{%- for app_name, app, mounts in mfe_data.mounted %} {{ app_name }}: # Work on this MFE for development image: "{{ MFE_DOCKER_IMAGE_DEV_PREFIX }}-{{ app_name }}-dev:{{ MFE_VERSION }}" ports: @@ -25,5 +17,13 @@ mfe: - lms environment: - "PORT={{ app['port'] }}" -{%- endif %} {%- endfor %} + + +{% if mfe_data.unmounted|length > 0 %} +mfe: + ports: + {%- for app_name, app in mfe_data.unmounted %} + - {{ app["port"] }}:8002 # {{ app_name }} + {%- endfor %} +{% endif %} diff --git a/tutormfe/plugin.py b/tutormfe/plugin.py index a3b8c8ad..70924799 100644 --- a/tutormfe/plugin.py +++ b/tutormfe/plugin.py @@ -11,6 +11,7 @@ from tutor.__about__ import __version_suffix__ from tutor.hooks import priorities from tutor.types import Config, get_typed +from tutor.bindmount import iter_mounts from .__about__ import __version__ from .hooks import MFE_APPS, MFE_ATTRS_TYPE, PLUGIN_SLOTS @@ -90,6 +91,24 @@ def get_mfes() -> dict[str, MFE_ATTRS_TYPE]: return MFE_APPS.apply({}) +class MFEMountData: + """Stores categorized mounted and unmounted MFEs.""" + + def __init__(self, mounts: list[str]): + self.mounted: list[tuple[str, MFE_ATTRS_TYPE, list[str]]] = [] + self.unmounted: list[tuple[str, MFE_ATTRS_TYPE]] = [] + self._categorize_mfes(mounts) + + def _categorize_mfes(self, mounts: list[str]) -> None: + """Populates mounted and unmounted MFE lists based on mount data.""" + for app_name, app in iter_mfes(): + mfe_mounts = list(iter_mounts(mounts, app_name)) + if mfe_mounts: + self.mounted.append((app_name, app, mfe_mounts)) + else: + self.unmounted.append((app_name, app)) + + @tutor_hooks.lru_cache def get_plugin_slots(mfe_name: str) -> list[tuple[str, str]]: """ @@ -131,6 +150,7 @@ def get_mfe(mfe_name: str) -> t.Union[MFE_ATTRS_TYPE, t.Any]: ("iter_mfes", iter_mfes), ("iter_plugin_slots", iter_plugin_slots), ("is_mfe_enabled", is_mfe_enabled), + ("MFEMountData", MFEMountData), ] )