diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4413187c3..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,13 +60,13 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Install dependencies 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 +74,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,13 +160,19 @@ 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 - uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Update version in package.json working-directory: electron-app @@ -186,7 +196,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/.gitignore b/electron-app/.gitignore index 2f4d5e1f1..a931cbac6 100644 --- a/electron-app/.gitignore +++ b/electron-app/.gitignore @@ -10,6 +10,8 @@ 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 diff --git a/electron-app/package.json b/electron-app/package.json index 58265f789..55235c394 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 Castello" }, + { "name": "Alejandro González" }, + { "name": "Vasyl Klymenko" } + ], "license": "MIT", "repository": { "type": "git", @@ -111,7 +118,8 @@ "linux": { "target": [ "AppImage", - "deb" + "deb", + "rpm" ], "icon": "icons/512x512.png", "category": "Utility", 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 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 }; diff --git a/electron-app/src/ipc/handlers.js b/electron-app/src/ipc/handlers.js index 5a4198d23..8d40d9a8c 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,7 @@ function setupIpcHandlers() { ipcMain.handle("save-config", async (event, config) => { try { await writeConfig(config); - await restartBackend(); - - reloadWindow(); - + app.emit("return-to-selector"); return true; } catch (error) { logger.electron.error("Error saving config:", error); @@ -106,10 +102,7 @@ function setupIpcHandlers() { ipcMain.handle("import-config", async () => { try { await importConfig(); - await restartBackend(); - - reloadWindow(); - + app.emit("return-to-selector"); return true; } catch (error) { logger.electron.error("Error importing config:", error); 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