diff --git a/.github/workflows/integration_delivery.yml b/.github/workflows/integration_delivery.yml index fdfe2ad8..49c8a3a4 100644 --- a/.github/workflows/integration_delivery.yml +++ b/.github/workflows/integration_delivery.yml @@ -75,11 +75,6 @@ jobs: echo "PYTHON_VERSION=$(python --version | cut -d' ' -f2)" >> $GITHUB_OUTPUT echo "PYTHON_VERSION=$(python --version | cut -d' ' -f2)" - - name: Install Poetry - uses: snok/install-poetry@v1 - with: - virtualenvs-create: true - - name: Check Cached Poetry id: cached-poetry uses: actions/cache/restore@v4 @@ -93,6 +88,12 @@ jobs: steps.get-python-version.outputs.PYTHON_VERSION }}-${{ hashFiles('poetry.lock') }} + - name: Install Poetry + if: steps.cached-poetry.outputs.cache-hit != 'true' + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + - name: Install dependencies if: steps.cached-poetry.outputs.cache-hit != 'true' run: | @@ -133,6 +134,7 @@ jobs: poetry-ubo-pod-python${{ needs.ubo-pod-dependencies.outputs.python-version }}-${{ hashFiles('poetry.lock') }} + fail-on-cache-miss: true - name: Create stub files run: | @@ -167,6 +169,7 @@ jobs: key: poetry-ubuntu-latest-python${{ env.PYTHON_VERSION }}-${{hashFiles('poetry.lock') }} + fail-on-cache-miss: true - name: Lint run: poetry run poe lint @@ -212,10 +215,11 @@ jobs: 'ubuntu-latest' }}-python${{ startsWith(matrix.runner, 'ubo-pod') && needs.ubo-pod-dependencies.outputs.python-version || env.PYTHON_VERSION }}-${{hashFiles('poetry.lock') }} + fail-on-cache-miss: true - name: Run Tests run: | - poetry run poe test --verbosity=2 --make-screenshots --cov-report=xml --cov-report=html --log-level=DEBUG -n ${{ startsWith(matrix.runner, 'ubo-pod') && '1' || 'auto' }} + poetry run poe test --verbosity=2 --make-screenshots --cov-report=xml --cov-report=html --log-level=DEBUG --log-cli-level=5 -n ${{ startsWith(matrix.runner, 'ubo-pod') && '1' || 'auto' }} - name: Collect Window Screenshots uses: actions/upload-artifact@v4 @@ -275,6 +279,7 @@ jobs: key: poetry-ubuntu-latest-python${{ env.PYTHON_VERSION }}-${{hashFiles('poetry.lock') }} + fail-on-cache-miss: true - name: Extract Version id: extract-version diff --git a/CHANGELOG.md b/CHANGELOG.md index b332b88e..d1ace5d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - feat(display): add display service and put display content in the bus via `DisplayRenderEvent` - fix(vscode): restart vscode process whenever a login/logout occurs +- fix(docker): avoid instantiating `RegisterRegularAppAction` in the reducer before service is loaded as it needs service to be registered ## Version 0.16.1 diff --git a/ubo_app/logging.py b/ubo_app/logging.py index 6e901e71..8d8d4fa0 100644 --- a/ubo_app/logging.py +++ b/ubo_app/logging.py @@ -130,8 +130,8 @@ def add_file_handler(logger: UboLogger, level: int = logging.DEBUG) -> None: file_handler = logging.handlers.RotatingFileHandler( f'{logger.name}.log', backupCount=3, + maxBytes=1000000, ) - file_handler.doRollover() file_handler.setLevel(level) file_handler.setFormatter( ExtraFormatter( diff --git a/ubo_app/services/000-display/setup.py b/ubo_app/services/000-display/setup.py index 0862788d..5c2258af 100644 --- a/ubo_app/services/000-display/setup.py +++ b/ubo_app/services/000-display/setup.py @@ -2,36 +2,15 @@ from __future__ import annotations -import atexit - -from ubo_app import display -from ubo_app.utils import IS_RPI - splash_screen = None -def turn_off() -> None: - """Destroy the display.""" - if IS_RPI: - from RPi import GPIO # pyright: ignore [reportMissingModuleSource] - - display.render_blank() - - GPIO.setmode(GPIO.BCM) - GPIO.setup(26, GPIO.OUT) - GPIO.output(26, GPIO.LOW) - GPIO.cleanup(26) - - def init_service() -> None: """Initialize the display service.""" - if IS_RPI: - from RPi import GPIO # pyright: ignore [reportMissingModuleSource] - - GPIO.setmode(GPIO.BCM) - GPIO.setup(26, GPIO.OUT) - GPIO.output(26, GPIO.HIGH) + from ubo_app import display + from ubo_app.constants import HEIGHT, WIDTH + if splash_screen: + display.render_block((0, 0, WIDTH - 1, HEIGHT - 1), splash_screen) + else: display.render_blank() - - atexit.register(turn_off) diff --git a/ubo_app/services/040-camera/setup.py b/ubo_app/services/040-camera/setup.py index d9689e36..ad6f4c36 100644 --- a/ubo_app/services/040-camera/setup.py +++ b/ubo_app/services/040-camera/setup.py @@ -16,7 +16,6 @@ from typing_extensions import override from ubo_gui.page import PageWidget -from ubo_app import display from ubo_app.store.core import CloseApplicationEvent, OpenApplicationEvent from ubo_app.store.main import store from ubo_app.store.services.camera import ( @@ -164,6 +163,8 @@ def feed_viewfinder(picamera2: Picamera2 | None) -> None: np.dstack(((color >> 8) & 0xFF, color & 0xFF)).flatten().tolist(), ) + from ubo_app import display + display.render_block( (0, 0, width - 1, height - 1), data_bytes, diff --git a/ubo_app/services/080-docker/reducer.py b/ubo_app/services/080-docker/reducer.py index 8098aca7..a9911ae8 100644 --- a/ubo_app/services/080-docker/reducer.py +++ b/ubo_app/services/080-docker/reducer.py @@ -5,7 +5,6 @@ from dataclasses import replace from typing import TYPE_CHECKING -from image_menus import IMAGE_MENUS from images_ import IMAGE_IDS, IMAGES from redux import ( BaseAction, @@ -18,13 +17,12 @@ ReducerResult, combine_reducers, ) -from ubo_gui.menu.types import ActionItem -from ubo_app.store.core import RegisterRegularAppAction from ubo_app.store.services.docker import ( DockerAction, DockerImageAction, DockerImageEvent, + DockerImageRegisterAppEvent, DockerImageSetDockerIdAction, DockerImageSetStatusAction, DockerRemoveUsernameAction, @@ -83,15 +81,7 @@ def image_reducer( image = IMAGES[action.key] return CompleteReducerResult( state=ImageState(id=image.id), - actions=[ - RegisterRegularAppAction( - menu_item=ActionItem( - label=image.label, - icon=image.icon, - action=IMAGE_MENUS[image.id], - ), - ), - ], + events=[DockerImageRegisterAppEvent(image=image.id)], ) raise InitializationActionError(action) diff --git a/ubo_app/services/080-docker/setup.py b/ubo_app/services/080-docker/setup.py index 3fc7ab62..6bc2ac09 100644 --- a/ubo_app/services/080-docker/setup.py +++ b/ubo_app/services/080-docker/setup.py @@ -11,17 +11,20 @@ import docker.errors from docker.models.containers import Container from docker.models.images import Image +from image_menus import IMAGE_MENUS from reducer import IMAGES from ubo_gui.constants import DANGER_COLOR from ubo_gui.menu.types import ActionItem, HeadedMenu, Item, SubMenuItem from ubo_app.constants import DOCKER_CREDENTIALS_TEMPLATE from ubo_app.store.core import ( + RegisterRegularAppAction, RegisterSettingAppAction, SettingsCategory, ) from ubo_app.store.main import store from ubo_app.store.services.docker import ( + DockerImageRegisterAppEvent, DockerRemoveUsernameAction, DockerSetStatusAction, DockerStatus, @@ -314,6 +317,19 @@ def registries_menu_items(usernames: dict[str, str]) -> Sequence[Item]: ] +def _register_image_app_entry(event: DockerImageRegisterAppEvent) -> None: + image = IMAGES[event.image] + store.dispatch( + RegisterRegularAppAction( + menu_item=ActionItem( + label=image.label, + icon=image.icon, + action=IMAGE_MENUS[image.id], + ), + ), + ) + + def init_service() -> None: """Initialize the service.""" register_persistent_store( @@ -347,6 +363,8 @@ def init_service() -> None: ), ) + store.subscribe_event(DockerImageRegisterAppEvent, _register_image_app_entry) + create_task( monitor_unit( 'docker.socket', diff --git a/ubo_app/services/080-docker/ubo_handle.py b/ubo_app/services/080-docker/ubo_handle.py index fec4e326..8b98bf78 100644 --- a/ubo_app/services/080-docker/ubo_handle.py +++ b/ubo_app/services/080-docker/ubo_handle.py @@ -11,10 +11,10 @@ def setup(service: Service) -> None: from reducer import reducer from setup import init_service - service.register_reducer(reducer) - init_service() + service.register_reducer(reducer) + register( service_id='docker', diff --git a/ubo_app/store/services/docker.py b/ubo_app/store/services/docker.py index e3f1a04b..0eedee64 100644 --- a/ubo_app/store/services/docker.py +++ b/ubo_app/store/services/docker.py @@ -100,6 +100,10 @@ class DockerImageEvent(DockerEvent): image: str +class DockerImageRegisterAppEvent(DockerImageEvent): + """Register image entry in apps in store.""" + + class ImageState(Immutable): """Image state."""