From f384f3409fcf7e5c9d10460381c059734dd1efb8 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Fri, 19 Jun 2026 20:12:57 +0200 Subject: [PATCH 01/12] chore: remove nix flake, nobody uses nix *sob* --- shell.nix | 200 ------------------------------------------------------ 1 file changed, 200 deletions(-) delete mode 100644 shell.nix diff --git a/shell.nix b/shell.nix deleted file mode 100644 index a84c7c6da..000000000 --- a/shell.nix +++ /dev/null @@ -1,200 +0,0 @@ -{ pkgs ? import {} }: - -let - # Pin nixpkgs for reproducibility - pinnedPkgs = import (builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/nixos-23.11.tar.gz"; - sha256 = "1ndiv385w1qyb3b18vw13991fzb9wg4cl21wglk89grsfsnra41k"; - }) {}; - - # Use pinned packages by default - finalPkgs = if pkgs == import {} then pinnedPkgs else pkgs; - -in finalPkgs.mkShell { - name = "hyperloop-h10-dev"; - - buildInputs = with finalPkgs; [ - # Go development - go - gotools - gopls - delve - - # Node.js development - nodejs_20 - nodePackages.npm - nodePackages.typescript - nodePackages.typescript-language-server - - # Python for testing - python3 - - # System dependencies - libpcap - pkg-config - - # Build tools - gnumake - gcc - - # Development utilities - git - ripgrep - jq - curl - wget - tmux - - # Optional productivity tools (can be removed for minimal setup) - watchman - ]; - - shellHook = '' - # Hyperloop H10 Development Environment - - # Set up environment variables - export GOPATH="$HOME/go" - export PATH="$GOPATH/bin:$PATH" - export NODE_ENV="development" - export CGO_ENABLED=1 - - # Create command functions for running services in tmux - ethernet-view() { - # Check if backend is built - if [ ! -f "backend/cmd/backend" ]; then - echo "Building backend first..." - make backend - fi - - # Kill existing session if it exists - tmux kill-session -t ethernet-view 2>/dev/null || true - - # Create new session - tmux new-session -d -s ethernet-view -n main - - # Start backend in first pane - tmux send-keys -t ethernet-view:main "cd backend/cmd && ./backend" C-m - - # Split horizontally and start ethernet-view - tmux split-window -t ethernet-view:main -h -p 50 - tmux send-keys -t ethernet-view:main.1 "cd ethernet-view && npm run dev" C-m - - # Add status pane at bottom - tmux split-window -t ethernet-view:main.0 -v -p 20 - tmux send-keys -t ethernet-view:main.2 "echo 'Logs/Status - Press Enter for shell'; read; bash" C-m - - # Configure pane titles - tmux select-pane -t ethernet-view:main.0 -T "Backend" - tmux select-pane -t ethernet-view:main.1 -T "Ethernet View (http://localhost:5174)" - tmux select-pane -t ethernet-view:main.2 -T "Logs/Shell" - tmux set-option -t ethernet-view pane-border-status top - - echo "Starting ethernet-view session..." - echo "Backend running on configured port" - echo "Ethernet View: http://localhost:5174" - - # Attach to session - tmux attach-session -t ethernet-view - } - - control-station() { - # Check if backend is built - if [ ! -f "backend/cmd/backend" ]; then - echo "Building backend first..." - make backend - fi - - # Kill existing session if it exists - tmux kill-session -t control-station 2>/dev/null || true - - # Create new session - tmux new-session -d -s control-station -n main - - # Start backend in first pane - tmux send-keys -t control-station:main "cd backend/cmd && ./backend" C-m - - # Split horizontally and start control-station - tmux split-window -t control-station:main -h -p 50 - tmux send-keys -t control-station:main.1 "cd control-station && npm run dev" C-m - - # Add status pane at bottom - tmux split-window -t control-station:main.0 -v -p 20 - tmux send-keys -t control-station:main.2 "echo 'Logs/Status - Press Enter for shell'; read; bash" C-m - - # Configure pane titles - tmux select-pane -t control-station:main.0 -T "Backend" - tmux select-pane -t control-station:main.1 -T "Control Station (http://localhost:5173)" - tmux select-pane -t control-station:main.2 -T "Logs/Shell" - tmux set-option -t control-station pane-border-status top - - echo "Starting control-station session..." - echo "Backend running on configured port" - echo "Control Station: http://localhost:5173" - - # Attach to session - tmux attach-session -t control-station - } - - # Export functions so they're available in the shell - export -f ethernet-view - export -f control-station - - # Ensure clean terminal state - clear - - # Check if dependencies need installation - check_dependencies() { - local install_needed=false - - if [ ! -d "common-front/node_modules" ]; then - echo "⚠️ Missing common-front dependencies" - install_needed=true - fi - - if [ ! -d "control-station/node_modules" ]; then - echo "⚠️ Missing control-station dependencies" - install_needed=true - fi - - if [ ! -d "ethernet-view/node_modules" ]; then - echo "⚠️ Missing ethernet-view dependencies" - install_needed=true - fi - - if [ "$install_needed" = true ]; then - echo "" - echo "Run 'make install' to install all dependencies" - fi - } - - # Display environment info - echo "Hyperloop H10 Development Environment" - echo "=====================================" - echo "" - echo "Environment:" - echo " Go version: $(go version | cut -d' ' -f3)" - echo " Node version: $(node --version)" - echo " NPM version: $(npm --version)" - echo "" - echo "Quick Start:" - echo " make install - Install all dependencies" - echo " make all - Build all components" - echo " ethernet-view - Run backend + Ethernet view in tmux" - echo " control-station - Run backend + Control station in tmux" - echo "" - echo "Individual Commands:" - echo " make backend - Build backend" - echo " make common-front - Build common frontend library" - echo " make control-station - Build control station" - echo " make ethernet-view - Build ethernet view" - echo "" - - check_dependencies - ''; - - # Prevent impurities - pure = true; - - # Additional environment variables for pure builds - NIX_ENFORCE_PURITY = 1; -} \ No newline at end of file From 1fc8edeba97d20b0dfc702fd21e2fa7864a974fd Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 10:40:21 +0200 Subject: [PATCH 02/12] chore: update .gitignore to exclude compilation builds of competition view --- electron-app/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electron-app/.gitignore b/electron-app/.gitignore index 2f4d5e1f1..8814da954 100644 --- a/electron-app/.gitignore +++ b/electron-app/.gitignore @@ -7,9 +7,9 @@ dist-ssr build binaries renderer -!renderer/ renderer/testing-view/ renderer/flashing-view/ +renderer/competition-view/ !renderer/mode-selector/ !renderer/mode-selector/** out From 2ebb69b170370881d07274536cf9778a63485ddd Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 10:41:48 +0200 Subject: [PATCH 03/12] fix: correct .gitignore --- electron-app/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/electron-app/.gitignore b/electron-app/.gitignore index 8814da954..a931cbac6 100644 --- a/electron-app/.gitignore +++ b/electron-app/.gitignore @@ -7,9 +7,11 @@ dist-ssr build binaries renderer +!renderer/ renderer/testing-view/ renderer/flashing-view/ renderer/competition-view/ +# include mode-selector in the build output !renderer/mode-selector/ !renderer/mode-selector/** out From 518b60363f878baaf7d22ff5dd55230364c9ca37 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 10:42:00 +0200 Subject: [PATCH 04/12] feat: electron integration --- electron-app/renderer/mode-selector/index.html | 2 ++ electron-app/src/app/modeSelector.js | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/electron-app/renderer/mode-selector/index.html b/electron-app/renderer/mode-selector/index.html index e554d12fc..871548df1 100644 --- a/electron-app/renderer/mode-selector/index.html +++ b/electron-app/renderer/mode-selector/index.html @@ -210,6 +210,7 @@

Control Station

+
@@ -229,6 +230,7 @@

Control Station

} }; document.getElementById('testing').addEventListener('click', () => sendMode('testing')); + document.getElementById('competition').addEventListener('click', () => sendMode('competition')); document.getElementById('flashing').addEventListener('click', () => sendMode('flashing')); const appVersionNode = document.getElementById('app-version'); diff --git a/electron-app/src/app/modeSelector.js b/electron-app/src/app/modeSelector.js index a64d54fcf..8150525b6 100644 --- a/electron-app/src/app/modeSelector.js +++ b/electron-app/src/app/modeSelector.js @@ -16,6 +16,7 @@ import { loadView } from "../windows/mainWindow.js"; const VALID_MODES = { testing: "testing-view", flashing: "flashing-view", + competition: "competition-view", default: "testing-view", }; @@ -79,7 +80,7 @@ async function showModeSelector(screenWidth, screenHeight) { logger.electron.header("Main application window created"); // Start services and only then load the selected view. - if (view === "testing-view" || view === "flashing-view") { + if (view === "testing-view" || view === "flashing-view" || view === "competition-view") { await startServices(screenWidth, screenHeight, view); } @@ -114,8 +115,8 @@ async function showModeSelector(screenWidth, screenHeight) { * @returns {Promise} */ async function startServices(screenWidth, screenHeight, view) { - // Start backend only for testing view - if (view === "testing-view") { + // Start backend for testing and competition views + if (view === "testing-view" || view === "competition-view") { const logWindow = createLogWindow(screenWidth, screenHeight); logWindow.show(); // Show the log window From b6c1b478588cb19baefe97a4986eddda5be6a623 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 17:41:00 +0200 Subject: [PATCH 05/12] chore(release): modify workflow --- .github/workflows/release.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4413187c3..43358a0ce 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -68,7 +68,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Build with Turbo - run: pnpm turbo build --filter=testing-view + run: pnpm turbo build --filter=testing-view --filter=competition-view - uses: actions/upload-artifact@v4 with: @@ -76,6 +76,12 @@ jobs: path: frontend/testing-view/dist/** retention-days: 1 + - uses: actions/upload-artifact@v4 + with: + name: competition-dist + path: frontend/competition-view/dist/** + retention-days: 1 + build-backend: name: Build Backend - ${{ matrix.os }} needs: determine-version @@ -156,6 +162,12 @@ jobs: name: frontend-dist path: electron-app/renderer/testing-view + - name: Download competition-view dist + uses: actions/download-artifact@v4 + with: + name: competition-dist + path: electron-app/renderer/competition-view + - uses: pnpm/action-setup@v4 with: version: 10.26.0 From 28aba99ba1f9e9ea45cc99abd47a8a936544bbb6 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 17:50:37 +0200 Subject: [PATCH 06/12] chore(release): recover rpm built --- .github/workflows/release.yaml | 2 +- electron-app/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 43358a0ce..59cd42daf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -198,7 +198,7 @@ jobs: run: | find electron-app/dist -maxdepth 1 -type f \ \( -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" \ - -o -name "*.dmg" -o -name "*.zip" -o -name "*.yml" -o -name "*.blockmap" \) \ + -o -name "*.rpm" -o -name "*.dmg" -o -name "*.zip" -o -name "*.yml" -o -name "*.blockmap" \) \ | xargs gh release upload v${{ needs.determine-version.outputs.version }} --clobber env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/electron-app/package.json b/electron-app/package.json index 58265f789..a9c66c157 100644 --- a/electron-app/package.json +++ b/electron-app/package.json @@ -111,7 +111,8 @@ "linux": { "target": [ "AppImage", - "deb" + "deb", + "rpm" ], "icon": "icons/512x512.png", "category": "Utility", From 910a0e5296fb8664d153f7a93013908449fb05ac Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:02:58 +0200 Subject: [PATCH 07/12] test: restore app --- electron-app/src/ipc/handlers.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/electron-app/src/ipc/handlers.js b/electron-app/src/ipc/handlers.js index 5a4198d23..bca5c2841 100644 --- a/electron-app/src/ipc/handlers.js +++ b/electron-app/src/ipc/handlers.js @@ -15,13 +15,12 @@ import { readConfig, writeConfig, } from "../config/configInstance.js"; -import { getBackendWorkingDir, restartBackend } from "../processes/backend.js"; +import { getBackendWorkingDir } from "../processes/backend.js"; import { logger } from "../utils/logger.js"; import { getCurrentView, getMainWindow, loadView, - reloadWindow, } from "../windows/mainWindow.js"; /** @@ -68,10 +67,8 @@ function setupIpcHandlers() { ipcMain.handle("save-config", async (event, config) => { try { await writeConfig(config); - await restartBackend(); - - reloadWindow(); - + app.relaunch(); + app.exit(0); return true; } catch (error) { logger.electron.error("Error saving config:", error); @@ -106,10 +103,8 @@ function setupIpcHandlers() { ipcMain.handle("import-config", async () => { try { await importConfig(); - await restartBackend(); - - reloadWindow(); - + app.relaunch(); + app.exit(0); return true; } catch (error) { logger.electron.error("Error importing config:", error); From a3f01b10ef0a27327a187cb49c8cfb0075e08a96 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:25:33 +0200 Subject: [PATCH 08/12] fix(workflow): remove deprecated --- .github/workflows/release.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 59cd42daf..4af91578e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,8 +11,6 @@ on: type: boolean default: true -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: determine-version: @@ -62,7 +60,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Install dependencies run: pnpm install --frozen-lockfile @@ -174,7 +172,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Update version in package.json working-directory: electron-app From b0ebc4da3b8e7b5f4bd40e9e54ab930851919c60 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:28:30 +0200 Subject: [PATCH 09/12] fix(updater): catch exception --- electron-app/src/app/updater.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/electron-app/src/app/updater.js b/electron-app/src/app/updater.js index c5a9c5dba..b41ed1b88 100644 --- a/electron-app/src/app/updater.js +++ b/electron-app/src/app/updater.js @@ -43,7 +43,9 @@ function setupUpdater() { }); // Check for updates - autoUpdater.checkForUpdates(); + autoUpdater.checkForUpdates().catch((error) => { + logger.electron.error("Update check failed:", error.message); + }); } export { setupUpdater }; From b51e51a69865176ccf509c22e93419c59bf8978e Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:40:03 +0200 Subject: [PATCH 10/12] docs(release): change autors --- electron-app/package.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/electron-app/package.json b/electron-app/package.json index a9c66c157..b661795a8 100644 --- a/electron-app/package.json +++ b/electron-app/package.json @@ -6,8 +6,15 @@ "type": "module", "author": { "name": "Hyperloop UPV", - "email": "max766667@gmail.com" + "email": "partners@hyperloopupv.com" }, + "contributors": [ + { "name": "Maxim Grivennyy", "email": "max766667@gmail.com" }, + { "name": "Javier Ribal del Río", "email": "javierribaldelrio@gmail.com" }, + { "name": "Lola Castelló" }, + { "name": "Alejandro Gonzalez" }, + { "name": "Vasyl Klymenko" } + ], "license": "MIT", "repository": { "type": "git", From cfba5ef431deeebaa8e55b8782de0e57f0a68803 Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:42:40 +0200 Subject: [PATCH 11/12] fix(docs): typos --- electron-app/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/electron-app/package.json b/electron-app/package.json index b661795a8..55235c394 100644 --- a/electron-app/package.json +++ b/electron-app/package.json @@ -11,8 +11,8 @@ "contributors": [ { "name": "Maxim Grivennyy", "email": "max766667@gmail.com" }, { "name": "Javier Ribal del Río", "email": "javierribaldelrio@gmail.com" }, - { "name": "Lola Castelló" }, - { "name": "Alejandro Gonzalez" }, + { "name": "Lola Castello" }, + { "name": "Alejandro González" }, { "name": "Vasyl Klymenko" } ], "license": "MIT", From f46eaaca27c547cb24a4e326c67737663b95f64e Mon Sep 17 00:00:00 2001 From: Javier Ribal del Rio Date: Sat, 20 Jun 2026 18:49:46 +0200 Subject: [PATCH 12/12] test: restart app --- electron-app/src/ipc/handlers.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/electron-app/src/ipc/handlers.js b/electron-app/src/ipc/handlers.js index bca5c2841..8d40d9a8c 100644 --- a/electron-app/src/ipc/handlers.js +++ b/electron-app/src/ipc/handlers.js @@ -67,8 +67,7 @@ function setupIpcHandlers() { ipcMain.handle("save-config", async (event, config) => { try { await writeConfig(config); - app.relaunch(); - app.exit(0); + app.emit("return-to-selector"); return true; } catch (error) { logger.electron.error("Error saving config:", error); @@ -103,8 +102,7 @@ function setupIpcHandlers() { ipcMain.handle("import-config", async () => { try { await importConfig(); - app.relaunch(); - app.exit(0); + app.emit("return-to-selector"); return true; } catch (error) { logger.electron.error("Error importing config:", error);