From 3944d7d3a7eab8ee769bc5530536cf1dd938566d Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 19:17:45 +0200 Subject: [PATCH 01/25] Add error handling when app cannot access volume paths --- app_forms/frm_main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app_forms/frm_main.py b/app_forms/frm_main.py index 29c06c4..6c604de 100644 --- a/app_forms/frm_main.py +++ b/app_forms/frm_main.py @@ -663,6 +663,9 @@ def refresh_local_address(self): except FileNotFoundError: self.addressDisplay.setText('Address file not found.') self.nameDisplay.setText('') + except PermissionError as e: + QMessageBox.critical(self, "Permission Denied", + f"Unable to read the address file at {address_path}. Please change the file permissions.") return def maybe_refresh_uptime(self): From 17fdcad8f7fb32074811ee5852d7d4a1bffd7b74 Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 19:31:48 +0200 Subject: [PATCH 02/25] Add messaging service for handling critical messages --- app_forms/frm_main.py | 6 +++--- services/messaging_service.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 services/messaging_service.py diff --git a/app_forms/frm_main.py b/app_forms/frm_main.py index 6c604de..3db7acb 100644 --- a/app_forms/frm_main.py +++ b/app_forms/frm_main.py @@ -29,7 +29,7 @@ from PyQt5.QtGui import QFont, QPixmap, QIcon import pyqtgraph as pg - +import services.messaging_service as messaging_service from utils.const import * from utils.docker import _DockerUtilsMixin from utils.updater import _UpdaterMixin @@ -664,8 +664,8 @@ def refresh_local_address(self): self.addressDisplay.setText('Address file not found.') self.nameDisplay.setText('') except PermissionError as e: - QMessageBox.critical(self, "Permission Denied", - f"Unable to read the address file at {address_path}. Please change the file permissions.") + messaging_service.show_critical_message(self, "Permission Denied", + f"Unable to read the file at {address_path}. Please change the file permissions.") return def maybe_refresh_uptime(self): diff --git a/services/messaging_service.py b/services/messaging_service.py new file mode 100644 index 0000000..41d23a2 --- /dev/null +++ b/services/messaging_service.py @@ -0,0 +1,12 @@ +from PyQt5.QtWidgets import QMessageBox + +def show_critical_message(parent, title, message): + """ + Display a critical message box. + + Parameters: + parent (QWidget): The parent widget. + title (str): The title of the message box. + message (str): The message to display. + """ + QMessageBox.critical(parent, title, message) \ No newline at end of file From 152399f7b3a8bbd525c89c9c3ec0e2b6fe6fcc8f Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 19:35:03 +0200 Subject: [PATCH 03/25] GH Actions: Add ubuntu 24.04 to build workflow --- .github/workflows/build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 56b1a08..0833257 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -56,7 +56,15 @@ jobs: name: EdgeNodeLauncher-WIN32 platformDependencies: "" - - os: ubuntu-latest + - os: ubuntu-24.04 + build: | + chmod +x build_scripts/unix_build.sh + ./build_scripts/unix_build.sh + zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-24.04.zip dist/* + name: EdgeNodeLauncher-LINUX_Ubuntu-24.04 + platformDependencies: sudo apt-get update && sudo apt install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing + + - os: ubuntu-22.04 build: | chmod +x build_scripts/unix_build.sh ./build_scripts/unix_build.sh From d50439d8be13794f3d04ca65bb14bd88290f21b8 Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 20:27:34 +0200 Subject: [PATCH 04/25] Encode credentials in base64 --- utils/const.py | 8 +++++--- utils/docker.py | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/utils/const.py b/utils/const.py index e31351c..18e7a27 100644 --- a/utils/const.py +++ b/utils/const.py @@ -1,3 +1,5 @@ +import os + from ver import __VER__ FULL_DEBUG = True @@ -46,9 +48,9 @@ AUTO_UPDATE_CHECK_INTERVAL = 60 -DEFAULT_MQTT_HOST = 'r9092118.ala.eu-central-1.emqxsl.com' -DEFAULT_MQTT_USER = 'corenaeural' -DEFAULT_MQTT_PASSWORD = '' +DEFAULT_MQTT_HOST = 'cjkwOTIxMTguYWxhLmV1LWNlbnRyYWwtMS5lbXF4c2wuY29t' +DEFAULT_MQTT_USER = 'Y29yZW5hZXVyYWw=' +DEFAULT_MQTT_PASSWORD = os.getenv("DEFAULT_MQTT_PASSWORD") ENV_TEMPLATE = ''' diff --git a/utils/docker.py b/utils/docker.py index e09c10b..0414d88 100644 --- a/utils/docker.py +++ b/utils/docker.py @@ -3,6 +3,7 @@ import platform import subprocess import platform +import base64 from pathlib import Path from collections import OrderedDict @@ -154,9 +155,9 @@ def __init__(self): self.docker_container_name = DOCKER_CONTAINER_NAME self.docker_tag = DOCKER_TAG self.node_id = self.get_node_id() - self.mqtt_host = DEFAULT_MQTT_HOST - self.mqtt_user = DEFAULT_MQTT_USER - self.mqtt_password = DEFAULT_MQTT_PASSWORD + self.mqtt_host = base64.b64decode(DEFAULT_MQTT_HOST).decode("utf-8") + self.mqtt_user = base64.b64decode(DEFAULT_MQTT_USER).decode("utf-8") + self.mqtt_password = base64.b64decode(DEFAULT_MQTT_PASSWORD).decode("utf-8") self._dev_mode = False self.run_with_sudo = False From 70fe32c33286c30e1f3fd4d172feb32fa8640888 Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 20:28:59 +0200 Subject: [PATCH 05/25] Set up password in .env file during project build --- .github/workflows/build.yml | 4 ++++ build_scripts/unix_build.sh | 2 +- build_scripts/win32_build.bat | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0833257..5d049b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,6 +110,10 @@ jobs: run: | pip install -r requirements.txt pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib + # Create .env file with Password + - name: Create .env file + run: | + echo "DEFAULT_MQTT_PASSWORD=${{ secrets.MQTT_K }}" > .env - name: Build app run: ${{ matrix.build }} - name: Zip App diff --git a/build_scripts/unix_build.sh b/build_scripts/unix_build.sh index e067d16..47619fc 100644 --- a/build_scripts/unix_build.sh +++ b/build_scripts/unix_build.sh @@ -1,7 +1,7 @@ #!/bin/bash # Your base PyInstaller command -PYINSTALLER_CMD="pyinstaller -w --onefile -n "EdgeNodeLauncher" main.py" +PYINSTALLER_CMD="pyinstaller -w --onefile --add-data ".env:." -n "EdgeNodeLauncher" main.py" # Combine the base command with the hidden imports and execute echo "$PYINSTALLER_CMD" diff --git a/build_scripts/win32_build.bat b/build_scripts/win32_build.bat index 320bc4d..fcb9723 100644 --- a/build_scripts/win32_build.bat +++ b/build_scripts/win32_build.bat @@ -2,7 +2,7 @@ setlocal EnableDelayedExpansion REM Your base PyInstaller command -set PYINSTALLER_CMD=pyinstaller -w --onefile -n "EdgeNodeLauncher" main.py +set PYINSTALLER_CMD=pyinstaller -w --onefile --add-data ".env:." -n "EdgeNodeLauncher" main.py REM Combine the base command with the hidden imports and execute echo %PYINSTALLER_CMD% From 81849d2231929349c25a63a97f1a732f43d0944e Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 21:31:42 +0200 Subject: [PATCH 06/25] Load env file on runtime --- main.py | 8 ++++++++ requirements.txt | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 47ba9a5..aea796f 100644 --- a/main.py +++ b/main.py @@ -2,10 +2,18 @@ import os from PyQt5.QtWidgets import QApplication from app_forms.frm_main import EdgeNodeLauncher +from dotenv import load_dotenv +from pathlib import Path # Set the working directory to the location of the executable # os.chdir(os.path.dirname(os.path.abspath(__file__))) +def load_env(): + """Load environment variables from the .env file.""" + dotenv_path = Path(__file__).parent / '.env' + load_dotenv(dotenv_path=dotenv_path) + + if __name__ == '__main__': app = QApplication(sys.argv) manager = EdgeNodeLauncher() diff --git a/requirements.txt b/requirements.txt index 0833462..b8ff24a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ PyQt5 matplotlib pyqtgraph -requests \ No newline at end of file +requests +dotenv \ No newline at end of file From f01b310f44295cc53d4040fa7a42abcafe71df9f Mon Sep 17 00:00:00 2001 From: vitalii Date: Wed, 8 Jan 2025 21:51:13 +0200 Subject: [PATCH 07/25] Load env file before any imports --- main.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index aea796f..76d4500 100644 --- a/main.py +++ b/main.py @@ -1,18 +1,18 @@ import sys import os -from PyQt5.QtWidgets import QApplication -from app_forms.frm_main import EdgeNodeLauncher from dotenv import load_dotenv from pathlib import Path -# Set the working directory to the location of the executable -# os.chdir(os.path.dirname(os.path.abspath(__file__))) +# Load environment variables should be done before any other in-app imports +# in order to access env variables in the app. +dotenv_path = Path(__file__).parent / '.env' +load_dotenv(dotenv_path=dotenv_path) -def load_env(): - """Load environment variables from the .env file.""" - dotenv_path = Path(__file__).parent / '.env' - load_dotenv(dotenv_path=dotenv_path) +from PyQt5.QtWidgets import QApplication +from app_forms.frm_main import EdgeNodeLauncher +# Set the working directory to the location of the executable +# os.chdir(os.path.dirname(os.path.abspath(__file__))) if __name__ == '__main__': app = QApplication(sys.argv) From 36faae80d6430bc3ed09257a1adcea16dd43b7cd Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 10:09:32 +0200 Subject: [PATCH 08/25] Revert "Load env file before any imports" This reverts commit f01b310f44295cc53d4040fa7a42abcafe71df9f. --- main.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 76d4500..aea796f 100644 --- a/main.py +++ b/main.py @@ -1,19 +1,19 @@ import sys import os -from dotenv import load_dotenv -from pathlib import Path - -# Load environment variables should be done before any other in-app imports -# in order to access env variables in the app. -dotenv_path = Path(__file__).parent / '.env' -load_dotenv(dotenv_path=dotenv_path) - from PyQt5.QtWidgets import QApplication from app_forms.frm_main import EdgeNodeLauncher +from dotenv import load_dotenv +from pathlib import Path # Set the working directory to the location of the executable # os.chdir(os.path.dirname(os.path.abspath(__file__))) +def load_env(): + """Load environment variables from the .env file.""" + dotenv_path = Path(__file__).parent / '.env' + load_dotenv(dotenv_path=dotenv_path) + + if __name__ == '__main__': app = QApplication(sys.argv) manager = EdgeNodeLauncher() From 7be71923fdbc6f448975628c7360897a3b6aecf3 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 10:09:32 +0200 Subject: [PATCH 09/25] Revert "Load env file on runtime" This reverts commit 81849d2231929349c25a63a97f1a732f43d0944e. --- main.py | 8 -------- requirements.txt | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/main.py b/main.py index aea796f..47ba9a5 100644 --- a/main.py +++ b/main.py @@ -2,18 +2,10 @@ import os from PyQt5.QtWidgets import QApplication from app_forms.frm_main import EdgeNodeLauncher -from dotenv import load_dotenv -from pathlib import Path # Set the working directory to the location of the executable # os.chdir(os.path.dirname(os.path.abspath(__file__))) -def load_env(): - """Load environment variables from the .env file.""" - dotenv_path = Path(__file__).parent / '.env' - load_dotenv(dotenv_path=dotenv_path) - - if __name__ == '__main__': app = QApplication(sys.argv) manager = EdgeNodeLauncher() diff --git a/requirements.txt b/requirements.txt index b8ff24a..0833462 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ PyQt5 matplotlib pyqtgraph -requests -dotenv \ No newline at end of file +requests \ No newline at end of file From 378d9324eb4f11c857766e2ad93f6ac17fb65ea1 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 10:09:32 +0200 Subject: [PATCH 10/25] Revert "Set up password in .env file during project build" This reverts commit 70fe32c33286c30e1f3fd4d172feb32fa8640888. --- .github/workflows/build.yml | 4 ---- build_scripts/unix_build.sh | 2 +- build_scripts/win32_build.bat | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d049b9..0833257 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,10 +110,6 @@ jobs: run: | pip install -r requirements.txt pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib - # Create .env file with Password - - name: Create .env file - run: | - echo "DEFAULT_MQTT_PASSWORD=${{ secrets.MQTT_K }}" > .env - name: Build app run: ${{ matrix.build }} - name: Zip App diff --git a/build_scripts/unix_build.sh b/build_scripts/unix_build.sh index 47619fc..e067d16 100644 --- a/build_scripts/unix_build.sh +++ b/build_scripts/unix_build.sh @@ -1,7 +1,7 @@ #!/bin/bash # Your base PyInstaller command -PYINSTALLER_CMD="pyinstaller -w --onefile --add-data ".env:." -n "EdgeNodeLauncher" main.py" +PYINSTALLER_CMD="pyinstaller -w --onefile -n "EdgeNodeLauncher" main.py" # Combine the base command with the hidden imports and execute echo "$PYINSTALLER_CMD" diff --git a/build_scripts/win32_build.bat b/build_scripts/win32_build.bat index fcb9723..320bc4d 100644 --- a/build_scripts/win32_build.bat +++ b/build_scripts/win32_build.bat @@ -2,7 +2,7 @@ setlocal EnableDelayedExpansion REM Your base PyInstaller command -set PYINSTALLER_CMD=pyinstaller -w --onefile --add-data ".env:." -n "EdgeNodeLauncher" main.py +set PYINSTALLER_CMD=pyinstaller -w --onefile -n "EdgeNodeLauncher" main.py REM Combine the base command with the hidden imports and execute echo %PYINSTALLER_CMD% From 8fa24e0b7e17c4cb3f99d0234c905c98fa76d3e1 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 10:16:20 +0200 Subject: [PATCH 11/25] Replace password placeholder with actual password before app build --- .github/workflows/build.yml | 6 ++++++ utils/const.py | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0833257..b9227f0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,6 +110,12 @@ jobs: run: | pip install -r requirements.txt pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib + # Replace the `****************` to MQTT_K in utils/const.py + - name: Replace placeholder in const.py + env: + MQTT_K: ${{ secrets.MQTT_K }} + run: | + sed -i 's/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/'"$MQTT_K"'/g' utils/const.py - name: Build app run: ${{ matrix.build }} - name: Zip App diff --git a/utils/const.py b/utils/const.py index 18e7a27..f1d787d 100644 --- a/utils/const.py +++ b/utils/const.py @@ -1,5 +1,3 @@ -import os - from ver import __VER__ FULL_DEBUG = True @@ -50,7 +48,7 @@ DEFAULT_MQTT_HOST = 'cjkwOTIxMTguYWxhLmV1LWNlbnRyYWwtMS5lbXF4c2wuY29t' DEFAULT_MQTT_USER = 'Y29yZW5hZXVyYWw=' -DEFAULT_MQTT_PASSWORD = os.getenv("DEFAULT_MQTT_PASSWORD") +DEFAULT_MQTT_PASSWORD = '****************' ENV_TEMPLATE = ''' From 783026ded10e77151cede285ef1a2dd804ceddc0 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 12:40:50 +0200 Subject: [PATCH 12/25] Increment version --- ver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ver.py b/ver.py index ac27694..2567c6e 100644 --- a/ver.py +++ b/ver.py @@ -1 +1 @@ -__VER__ = '0.8.6' +__VER__ = '0.8.7' From d2c91b371e5395f384a5d25aaa670d41abcf7346 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 13:07:29 +0200 Subject: [PATCH 13/25] Update workflow to do platform-specific password replacement --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b9227f0..8ebf1d8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -115,7 +115,12 @@ jobs: env: MQTT_K: ${{ secrets.MQTT_K }} run: | - sed -i 's/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/'"$MQTT_K"'/g' utils/const.py + if [ "$RUNNER_OS" = "Windows" ]; then + $filePath = "utils/const.py" + (Get-Content $filePath) -replace '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*', "${{ env.MQTT_K }}" | Set-Content $filePath + else + sed -i "s/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/${MQTT_K}/g" utils/const.py + fi - name: Build app run: ${{ matrix.build }} - name: Zip App From 62ad83dbcb25e6e92e20b8368a51de6e2588f323 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 11:14:17 +0200 Subject: [PATCH 14/25] Implement separate steps for windows and linux password replacement --- .github/workflows/build.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ebf1d8..8527bc0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ name: Multi-step multi-platform build on: push: - branches: ["main"] + branches: ["main", "test-build"] pull_request: branches: ["main"] @@ -111,16 +111,19 @@ jobs: pip install -r requirements.txt pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib # Replace the `****************` to MQTT_K in utils/const.py - - name: Replace placeholder in const.py + - name: Replace placeholder in const.py (Windows) + if: runner.os == 'Windows' env: MQTT_K: ${{ secrets.MQTT_K }} run: | - if [ "$RUNNER_OS" = "Windows" ]; then - $filePath = "utils/const.py" - (Get-Content $filePath) -replace '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*', "${{ env.MQTT_K }}" | Set-Content $filePath - else - sed -i "s/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/${MQTT_K}/g" utils/const.py - fi + $filePath = "utils/const.py" + (Get-Content $filePath) -replace '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*', "${{ env.MQTT_K }}" | Set-Content $filePath + - name: Replace placeholder in const.py (Linux) + if: runner.os == 'Linux' + env: + MQTT_K: ${{ secrets.MQTT_K }} + run: | + sed -i "s/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/${MQTT_K}/g" utils/const.py - name: Build app run: ${{ matrix.build }} - name: Zip App From 84bf46cefd478bbce577e4ff2ab15e9c75d27d7f Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 16:49:49 +0200 Subject: [PATCH 15/25] Fix workflow --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8527bc0..6f49261 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ name: Multi-step multi-platform build on: push: - branches: ["main", "test-build"] + branches: ["main"] pull_request: branches: ["main"] From 9bad8a3b3245f434099a62ac667f685951d5725d Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 20:49:35 +0200 Subject: [PATCH 16/25] Remove credentials from docker template --- utils/const.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/const.py b/utils/const.py index f1d787d..1dcefca 100644 --- a/utils/const.py +++ b/utils/const.py @@ -69,10 +69,7 @@ # MQTT -EE_MQTT_HOST={} EE_MQTT_PORT=8883 -EE_MQTT_USER={} -EE_MQTT={} EE_MQTT_SUBTOPIC=address EE_MQTT_CERT= From f6023a6b5170490b4b844f150da25d1ee295b63f Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 23:45:36 +0200 Subject: [PATCH 17/25] Use env variables to set up credentials --- utils/docker.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/utils/docker.py b/utils/docker.py index 0414d88..f5f2991 100644 --- a/utils/docker.py +++ b/utils/docker.py @@ -227,6 +227,9 @@ def __setup_docker_run(self): self.__CMD += [ '--rm', # remove the container when it exits '--env-file', '.env', #f'"{str(self.env_file)}"', # pass the .env file to the container + '-e', f'MQTT_HOST={self.mqtt_host}', # pass the MQTT host to the container + '-e', f'MQTT_USER={self.mqtt_user}', # pass the MQTT user to the container + '-e', f'MQTT_PASSWORD={self.mqtt_password}', # pass the MQTT password to the container '-v', f'{DOCKER_VOLUME}:/edge_node/_local_cache', # mount the volume '--name', self.docker_container_name, '-d', ] @@ -309,23 +312,6 @@ def __check_env_keys(self): except FileNotFoundError: QMessageBox.warning(self, 'Error', '.env file not found.') return False - - # Check if the EE_MQTT key is present and set - if 'EE_MQTT' not in env_vars or not env_vars['EE_MQTT']: - # Prompt the user for the MQTT password - password, ok = QInputDialog.getText(self, 'MQTT Broker password Required', 'Enter MQTT broker password:') - if ok and password: - # Update the env_vars dictionary with the new password - env_vars['EE_MQTT'] = password - # Resave the .env file with the updated key - with open(self.env_file, 'w') as file: - for key, value in env_vars.items(): - file.write(f'{key}={value}\n') - QMessageBox.information(self, 'Success', 'MQTT password set successfully.') - return True - else: - QMessageBox.warning(self, 'Error', 'MQTT password is required to continue.') - return False return True From 617aa9f6ef31d5c6708cee5f12fd14a60ddec075 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 23:46:09 +0200 Subject: [PATCH 18/25] Obfuscate password in logs --- utils/docker.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/docker.py b/utils/docker.py index f5f2991..a4d9041 100644 --- a/utils/docker.py +++ b/utils/docker.py @@ -260,8 +260,11 @@ def get_cmd(self): result = self.__CMD + ['-p', '80:80', self.docker_image] else: result = self.__CMD + [self.docker_image] - self.add_log("Docker command: '{}'".format(" ".join(result)), debug=True) - return result + + obfuscated_result = ['*' * len(self.mqtt_password) if self.mqtt_password in item else item for item in result] + + self.add_log("Docker command: '{}'".format(" ".join(obfuscated_result)), debug=True) + return obfuscated_result def get_clean_cmd(self): From d68bc83510628d03ae5f7a14ea7ff2d5348f3ea4 Mon Sep 17 00:00:00 2001 From: vitalii Date: Thu, 9 Jan 2025 23:46:28 +0200 Subject: [PATCH 19/25] Add extra logging when env is not ok --- utils/docker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/docker.py b/utils/docker.py index a4d9041..246bee2 100644 --- a/utils/docker.py +++ b/utils/docker.py @@ -393,6 +393,7 @@ def is_container_running(self): def launch_container(self): is_env_ok = self.__check_env_keys() if not is_env_ok: + self.add_log('Environment is not ok. Could not start the container.') return self.add_log('Updating image...') self.__maybe_docker_pull() From 3e1c8e2d95857b03ae065c218f12266201009f1e Mon Sep 17 00:00:00 2001 From: vitalii Date: Fri, 10 Jan 2025 20:50:13 +0200 Subject: [PATCH 20/25] Update env variables names --- utils/docker.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/utils/docker.py b/utils/docker.py index 246bee2..95f2eb7 100644 --- a/utils/docker.py +++ b/utils/docker.py @@ -227,9 +227,9 @@ def __setup_docker_run(self): self.__CMD += [ '--rm', # remove the container when it exits '--env-file', '.env', #f'"{str(self.env_file)}"', # pass the .env file to the container - '-e', f'MQTT_HOST={self.mqtt_host}', # pass the MQTT host to the container - '-e', f'MQTT_USER={self.mqtt_user}', # pass the MQTT user to the container - '-e', f'MQTT_PASSWORD={self.mqtt_password}', # pass the MQTT password to the container + '-e', f'EE_MQTT_HOST={self.mqtt_host}', # pass the MQTT host to the container + '-e', f'EE_MQTT_USER={self.mqtt_user}', # pass the MQTT user to the container + '-e', f'EE_MQTT={self.mqtt_password}', # pass the MQTT password to the container '-v', f'{DOCKER_VOLUME}:/edge_node/_local_cache', # mount the volume '--name', self.docker_container_name, '-d', ] @@ -246,9 +246,12 @@ def __setup_docker_run(self): self.__CMD_CLEAN.insert(0, 'sudo') self.__CMD_STOP.insert(0, 'sudo') self.__CMD_INSPECT.insert(0, 'sudo') - + + run_cmd = " ".join(self.get_cmd()) + obfuscated_cmd = run_cmd.replace(self.mqtt_password, '*' * len(self.mqtt_password)) + self.add_log('Docker run command setup complete:') - self.add_log(' - Run: {}'.format(" ".join(self.get_cmd()))) + self.add_log(' - Run: {}'.format(obfuscated_cmd)) self.add_log(' - Clean: {}'.format(" ".join(self.__CMD_CLEAN))) self.add_log(' - Stop: {}'.format(" ".join(self.__CMD_STOP))) self.add_log(' - Inspect: {}'.format(" ".join(self.__CMD_INSPECT))) @@ -260,12 +263,7 @@ def get_cmd(self): result = self.__CMD + ['-p', '80:80', self.docker_image] else: result = self.__CMD + [self.docker_image] - - obfuscated_result = ['*' * len(self.mqtt_password) if self.mqtt_password in item else item for item in result] - - self.add_log("Docker command: '{}'".format(" ".join(obfuscated_result)), debug=True) - return obfuscated_result - + return result def get_clean_cmd(self): return self.__CMD_CLEAN From d722b6d5973892b1059510b8f8913b4f1d332a8b Mon Sep 17 00:00:00 2001 From: Andrei Ionut Damian Date: Fri, 10 Jan 2025 12:58:14 +0200 Subject: [PATCH 21/25] cherry-pick fix: refactor local address info --- app_forms/frm_main.py | 28 +++++++++++++++++----------- utils/const.py | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app_forms/frm_main.py b/app_forms/frm_main.py index 3db7acb..f4803be 100644 --- a/app_forms/frm_main.py +++ b/app_forms/frm_main.py @@ -533,7 +533,8 @@ def check_data(self, data): data_size = len(data['timestamps']) if data_size > 0 and data_size > MAX_HISTORY_QUEUE: for key in data: - data[key] = data[key][-MAX_HISTORY_QUEUE:] + if isinstance(data[key], list): + data[key] = data[key][-MAX_HISTORY_QUEUE:] start_time = data['timestamps'][0] end_time = data['timestamps'][-1] self.add_log('Data loaded & cleaned: {} timestamps from {} to {}'.format( @@ -647,17 +648,20 @@ def refresh_local_address(self): address_path = os.path.join(self.volume_path, LOCAL_ADDRESS_FILE) try: with open(address_path, 'r') as file: - address_info = [x for x in file.read().split(' ') if len(x) > 0] - if len(address_info) == 0: - raise FileNotFoundError - if address_info[0] != self.node_addr: - self.node_addr = address_info[0] - self.node_name = address_info[1] if len(address_info) > 1 else '' - str_display = address_info[0][:8] + '...' + address_info[0][-8:] + data = json.load(file) + node_addr = data['address'] + node_alias= data.get('alias', '') + node_eth_addr = data.get('eth_address', '') + node_signature = data.get('signature', '') + self.node_eth_addr = node_eth_addr + self.node_signature = node_signature + if node_addr != self.node_addr: + self.node_addr = node_addr + self.node_name = node_alias + str_display = node_addr[:8] + '...' + node_addr[-8:] self.addressDisplay.setText('Addr: ' + str_display) - self.nameDisplay.setText('Name: ' + address_info[1] if len(address_info) > 1 else '') - self.add_log(f'Local address updated: {self.node_addr} : {self.node_name}') - + self.nameDisplay.setText('Name: ' + node_alias) + self.add_log(f'Local address updated: {self.node_addr} : {self.node_name}, ETH: {self.node_eth_addr}') # endif new address # endwith open except FileNotFoundError: @@ -666,6 +670,8 @@ def refresh_local_address(self): except PermissionError as e: messaging_service.show_critical_message(self, "Permission Denied", f"Unable to read the file at {address_path}. Please change the file permissions.") + except Exception as e: + self.add_log(f'Error loading address: {e}', debug=True) return def maybe_refresh_uptime(self): diff --git a/utils/const.py b/utils/const.py index 1dcefca..5be088d 100644 --- a/utils/const.py +++ b/utils/const.py @@ -17,7 +17,7 @@ LINUX_VOLUME_PATH = '/var/lib/docker/volumes/naeural_vol/_data' LOCAL_HISTORY_FILE = '_data/local_history.json' E2_PEM_FILE = '_data/e2.pem' -LOCAL_ADDRESS_FILE = '_data/local_address.txt' +LOCAL_ADDRESS_FILE = '_data/local_address.json' CONFIG_STARTUP_FILE = 'config_startup.json' CONFIG_APP_FILE = '_data/box_configuration/config_app.txt' ADDRS_FILE = 'authorized_addrs' From cddb76fb91352e134fc1f7596b805b8003ad4288 Mon Sep 17 00:00:00 2001 From: vitalii Date: Sun, 12 Jan 2025 18:42:55 +0200 Subject: [PATCH 22/25] Add GH action to build the launcher when a PR to main is open --- .github/workflows/pr-build.yml | 119 +++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 .github/workflows/pr-build.yml diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml new file mode 100644 index 0000000..323eb47 --- /dev/null +++ b/.github/workflows/pr-build.yml @@ -0,0 +1,119 @@ +name: Multi-step multi-platform build on PR to main branch and saves the artifacts + +on: + pull_request: + branches: ["main"] + +jobs: + check-version: + runs-on: ubuntu-latest + outputs: + should-run: ${{ steps.check-version.outputs.should-run }} + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetches all history for all branches and tags + + # Step to fetch the latest release version + - name: Get latest release version + id: latest-version + run: | + LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`) + echo "Latest tag is $LATEST_TAG" + echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV + + # Step to read version.py and compare + - name: Check version in ver.py + id: check-version + run: | + CURRENT_VERSION=$(cat ver.py | grep -o "'.*'") + echo "Current version is $CURRENT_VERSION" + + if [ "$CURRENT_VERSION" == "$LATEST_TAG" ]; then + echo "Version $CURRENT_VERSION has not been incremented vs already released $LATEST_TAG. Build will be cancelled." + echo "::set-output name=should-run::false" + exit 1 + else + echo "Current version $CURRENT_VERSION differs from latest tag $LATEST_TAG. Build will continue." + echo "::set-output name=should-run::true" + fi + + build: + needs: check-version + if: needs.check-version.outputs.should-run == 'true' + + strategy: + matrix: + include: + - os: windows-latest + build: ./build_scripts/win32_build.bat + zip: Compress-Archive -Path dist/* -Destination EdgeNodeLauncher-WIN32.zip + name: EdgeNodeLauncher-WIN32 + platformDependencies: "" + + - os: ubuntu-24.04 + build: | + chmod +x build_scripts/unix_build.sh + ./build_scripts/unix_build.sh + zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-24.04.zip dist/* + name: EdgeNodeLauncher-LINUX_Ubuntu-24.04 + platformDependencies: sudo apt-get update && sudo apt install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing + + - os: ubuntu-22.04 + build: | + chmod +x build_scripts/unix_build.sh + ./build_scripts/unix_build.sh + zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-22.04.zip dist/* + name: EdgeNodeLauncher-LINUX_Ubuntu-22.04 + platformDependencies: sudo apt-get update && sudo apt install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing + + - os: ubuntu-20.04 + build: | + chmod +x build_scripts/unix_build.sh + ./build_scripts/unix_build.sh + zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-20.04.zip dist/* + name: EdgeNodeLauncher-LINUX_Ubuntu-20.04 + platformDependencies: sudo apt-get update && sudo apt-get install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing + + name: Build installers ${{ matrix.os }} + runs-on: ${{ matrix.os }} + permissions: write-all + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10.11 + uses: actions/setup-python@v2 + with: + python-version: "3.10.11" + - run: ${{ matrix.platformDependencies }} + - name: Setup env + run: | + pip install -r requirements.txt + pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib + # Replace the `****************` to MQTT_K in utils/const.py + - name: Replace placeholder in const.py (Windows) + if: runner.os == 'Windows' + env: + MQTT_K: ${{ secrets.MQTT_K }} + run: | + $filePath = "utils/const.py" + (Get-Content $filePath) -replace '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*', "${{ env.MQTT_K }}" | Set-Content $filePath + - name: Replace placeholder in const.py (Linux) + if: runner.os == 'Linux' + env: + MQTT_K: ${{ secrets.MQTT_K }} + run: | + sed -i "s/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/${MQTT_K}/g" utils/const.py + + - name: Build app + run: ${{ matrix.build }} + + - name: Zip App + run: ${{ matrix.zip }} + + - name: Save zip File as artifact + uses: actions/upload-artifact@v3 + with: + name: release + path: ./${{ matrix.name }}.zip \ No newline at end of file From 34cba944ca4d997d630bc469a7a80ba0299940fe Mon Sep 17 00:00:00 2001 From: vitalii Date: Sun, 12 Jan 2025 18:51:58 +0200 Subject: [PATCH 23/25] Save all builds in one zip --- .github/workflows/pr-build.yml | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 323eb47..e0c23f0 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -15,7 +15,6 @@ jobs: with: fetch-depth: 0 # Fetches all history for all branches and tags - # Step to fetch the latest release version - name: Get latest release version id: latest-version run: | @@ -23,7 +22,6 @@ jobs: echo "Latest tag is $LATEST_TAG" echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV - # Step to read version.py and compare - name: Check version in ver.py id: check-version run: | @@ -48,7 +46,6 @@ jobs: include: - os: windows-latest build: ./build_scripts/win32_build.bat - zip: Compress-Archive -Path dist/* -Destination EdgeNodeLauncher-WIN32.zip name: EdgeNodeLauncher-WIN32 platformDependencies: "" @@ -56,7 +53,6 @@ jobs: build: | chmod +x build_scripts/unix_build.sh ./build_scripts/unix_build.sh - zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-24.04.zip dist/* name: EdgeNodeLauncher-LINUX_Ubuntu-24.04 platformDependencies: sudo apt-get update && sudo apt install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing @@ -64,7 +60,6 @@ jobs: build: | chmod +x build_scripts/unix_build.sh ./build_scripts/unix_build.sh - zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-22.04.zip dist/* name: EdgeNodeLauncher-LINUX_Ubuntu-22.04 platformDependencies: sudo apt-get update && sudo apt install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing @@ -72,7 +67,6 @@ jobs: build: | chmod +x build_scripts/unix_build.sh ./build_scripts/unix_build.sh - zip: zip -r EdgeNodeLauncher-LINUX_Ubuntu-20.04.zip dist/* name: EdgeNodeLauncher-LINUX_Ubuntu-20.04 platformDependencies: sudo apt-get update && sudo apt-get install -y '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev --fix-missing @@ -91,7 +85,7 @@ jobs: run: | pip install -r requirements.txt pip3 install --upgrade PyInstaller pyinstaller-hooks-contrib - # Replace the `****************` to MQTT_K in utils/const.py + - name: Replace placeholder in const.py (Windows) if: runner.os == 'Windows' env: @@ -99,6 +93,7 @@ jobs: run: | $filePath = "utils/const.py" (Get-Content $filePath) -replace '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*', "${{ env.MQTT_K }}" | Set-Content $filePath + - name: Replace placeholder in const.py (Linux) if: runner.os == 'Linux' env: @@ -109,11 +104,30 @@ jobs: - name: Build app run: ${{ matrix.build }} - - name: Zip App - run: ${{ matrix.zip }} + - name: Save build artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.name }}-build + path: dist/* + + collect-artifacts: + needs: build + runs-on: ubuntu-latest + permissions: write-all + + steps: + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.name }}-build + path: ./all-builds + + - name: Create final zip + run: | + zip -r final-build-${{ github.event.pull_request.number }}-${{ github.sha }}.zip ./all-builds - - name: Save zip File as artifact + - name: Upload final zip uses: actions/upload-artifact@v3 with: - name: release - path: ./${{ matrix.name }}.zip \ No newline at end of file + name: final-build-${{ github.event.pull_request.number }}-${{ github.sha }} + path: final-build-${{ github.event.pull_request.number }}-${{ github.sha }}.zip \ No newline at end of file From 450a7a47ac8a496535ea958359ae8e9ddd9f6153 Mon Sep 17 00:00:00 2001 From: vitalii Date: Sun, 12 Jan 2025 19:21:58 +0200 Subject: [PATCH 24/25] Remove PR trigger from build workflow --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f49261..601a19b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,8 +5,6 @@ name: Multi-step multi-platform build on: push: branches: ["main"] - pull_request: - branches: ["main"] jobs: check-version: From a3aa7ed5c74f6ad2284b309a984cf3e4ff648a10 Mon Sep 17 00:00:00 2001 From: vitalii Date: Sun, 12 Jan 2025 19:29:41 +0200 Subject: [PATCH 25/25] Add PR ID and commit hash to artifact name --- .github/workflows/pr-build.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index e0c23f0..e49420b 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -107,7 +107,7 @@ jobs: - name: Save build artifacts uses: actions/upload-artifact@v3 with: - name: ${{ matrix.name }}-build + name: ${{ matrix.name }}-build-${{ github.event.pull_request.number }}-${{ github.sha }} path: dist/* collect-artifacts: @@ -119,15 +119,23 @@ jobs: - name: Download build artifacts uses: actions/download-artifact@v3 with: - name: ${{ matrix.name }}-build - path: ./all-builds + name: EdgeNodeLauncher-WIN32-build-${{ github.event.pull_request.number }}-${{ github.sha }} + path: ./all-builds/EdgeNodeLauncher-WIN32 - - name: Create final zip - run: | - zip -r final-build-${{ github.event.pull_request.number }}-${{ github.sha }}.zip ./all-builds + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: EdgeNodeLauncher-LINUX_Ubuntu-24.04-build-${{ github.event.pull_request.number }}-${{ github.sha }} + path: ./all-builds/EdgeNodeLauncher-LINUX_Ubuntu-24.04 - - name: Upload final zip - uses: actions/upload-artifact@v3 + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: EdgeNodeLauncher-LINUX_Ubuntu-22.04-build-${{ github.event.pull_request.number }}-${{ github.sha }} + path: ./all-builds/EdgeNodeLauncher-LINUX_Ubuntu-22.04 + + - name: Download build artifacts + uses: actions/download-artifact@v3 with: - name: final-build-${{ github.event.pull_request.number }}-${{ github.sha }} - path: final-build-${{ github.event.pull_request.number }}-${{ github.sha }}.zip \ No newline at end of file + name: EdgeNodeLauncher-LINUX_Ubuntu-20.04-build-${{ github.event.pull_request.number }}-${{ github.sha }} + path: ./all-builds/EdgeNodeLauncher-LINUX_Ubuntu-20.04