From 07f4ea8277011f4d46ba21cc4641edc5c077c908 Mon Sep 17 00:00:00 2001 From: Danilo Reyes Date: Sun, 2 Nov 2025 00:42:46 -0600 Subject: [PATCH] refactor: clean up flake.nix and nixos configurations for improved readability and organization - Reformatted `flake.nix` for better structure and consistency, including adjustments to package lists and added metadata for applications. - Updated `nixos/gitea-runner.nix` to streamline configuration and improve clarity. - Refined `nixos/tests.nix` by consolidating service definitions and enhancing test scripts for better maintainability and readability. --- flake.nix | 136 ++++++++++++++-------- nixos/gitea-runner.nix | 38 ++++--- nixos/tests.nix | 248 ++++++++++++++++++++++------------------- 3 files changed, 241 insertions(+), 181 deletions(-) diff --git a/flake.nix b/flake.nix index efe715e..f925049 100644 --- a/flake.nix +++ b/flake.nix @@ -6,37 +6,41 @@ flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: + outputs = + { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = nixpkgs.legacyPackages.${system}; - - pythonEnv = pkgs.python3.withPackages (ps: with ps; [ - # Core backend dependencies - fastapi - uvicorn - sqlalchemy - alembic - pydantic - pydantic-settings # Settings management - psycopg2 # PostgreSQL driver - # Auth & Security - python-jose - passlib - bcrypt # Password hashing backend for passlib - email-validator # Email validation for pydantic - # Image processing - pillow - # Storage - boto3 - # HTTP & uploads - httpx - python-multipart - # Testing - pytest - pytest-cov - pytest-asyncio - ]); + + pythonEnv = pkgs.python3.withPackages ( + ps: with ps; [ + # Core backend dependencies + fastapi + uvicorn + sqlalchemy + alembic + pydantic + pydantic-settings # Settings management + psycopg2 # PostgreSQL driver + # Auth & Security + python-jose + passlib + bcrypt # Password hashing backend for passlib + email-validator # Email validation for pydantic + # Image processing + pillow + # Storage + boto3 + # HTTP & uploads + httpx + python-multipart + # Testing + pytest + pytest-cov + pytest-asyncio + ] + ); in { devShells.default = pkgs.mkShell { @@ -45,25 +49,25 @@ pythonEnv uv ruff - + # Database postgresql - + # Frontend nodejs nodePackages.npm - + # Image processing imagemagick - + # Storage minio minio-client - + # Development tools git direnv - + # Optional: monitoring/debugging # redis ]; @@ -89,7 +93,7 @@ echo " App: http://localhost:5173" echo " MinIO UI: http://localhost:9001" echo "" - + # Set up environment variables export DATABASE_URL="postgresql://localhost/webref" export PYTHONPATH="$PWD/backend:$PYTHONPATH" @@ -98,12 +102,24 @@ # Apps - Scripts that can be run with `nix run` apps = { + default = { + type = "app"; + program = "${pkgs.writeShellScript "help" '' + echo "Available commands:" + echo " nix run .#lint - Run linting checks" + echo " nix run .#lint-fix - Auto-fix linting issues" + ''}"; + meta = { + description = "Show available commands"; + }; + }; + # Unified linting for all code lint = { type = "app"; program = "${pkgs.writeShellScript "lint" '' set -e - + # Backend Python linting echo "🔍 Linting backend Python code..." if [ -d "backend" ]; then @@ -115,7 +131,7 @@ echo "⚠ Not in project root (backend/ not found)" exit 1 fi - + # Frontend linting (if node_modules exists) if [ -d "frontend/node_modules" ]; then echo "" @@ -128,18 +144,21 @@ else echo "⚠ Frontend node_modules not found, run 'npm install' first" fi - + echo "" echo "✅ All linting checks passed!" ''}"; + meta = { + description = "Run linting checks on backend and frontend code"; + }; }; - + # Auto-fix linting issues lint-fix = { type = "app"; program = "${pkgs.writeShellScript "lint-fix" '' set -e - + echo "🔧 Auto-fixing backend Python code..." if [ -d "backend" ]; then cd backend @@ -150,7 +169,7 @@ echo "⚠ Not in project root (backend/ not found)" exit 1 fi - + if [ -d "frontend/node_modules" ]; then echo "" echo "🔧 Auto-fixing frontend code..." @@ -158,33 +177,52 @@ ${pkgs.nodePackages.prettier}/bin/prettier --write src/ cd .. fi - + echo "" echo "✅ Auto-fix complete!" ''}"; + meta = { + description = "Auto-fix linting issues in backend and frontend code"; + }; }; }; # Package definitions (for production deployment) - packages = { + packages = rec { # Backend package backend = pkgs.python3Packages.buildPythonApplication { pname = "webref-backend"; version = "1.0.0"; + pyproject = true; src = ./backend; + + build-system = with pkgs.python3Packages; [ + setuptools + ]; + propagatedBuildInputs = with pkgs.python3Packages; [ fastapi uvicorn sqlalchemy alembic pydantic + pydantic-settings + psycopg2 python-jose passlib pillow boto3 httpx python-multipart + email-validator + bcrypt ]; + + meta = { + description = "Reference Board Viewer - Backend API"; + homepage = "https://github.com/yourusername/webref"; + license = pkgs.lib.licenses.mit; + }; }; # Frontend package @@ -192,7 +230,7 @@ pname = "webref-frontend"; version = "1.0.0"; src = ./frontend; - npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Update after first build + npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Update after first build buildPhase = '' npm run build ''; @@ -200,7 +238,14 @@ mkdir -p $out cp -r build/* $out/ ''; + meta = { + description = "Reference Board Viewer - Frontend SPA"; + homepage = "https://github.com/yourusername/webref"; + license = pkgs.lib.licenses.mit; + }; }; + + default = backend; }; # NixOS VM tests @@ -208,4 +253,3 @@ } ); } - diff --git a/nixos/gitea-runner.nix b/nixos/gitea-runner.nix index ea28235..ffe259d 100644 --- a/nixos/gitea-runner.nix +++ b/nixos/gitea-runner.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, ... }: +{ pkgs, ... }: { # Gitea Actions Runner Configuration @@ -6,36 +6,36 @@ services.gitea-actions-runner = { package = pkgs.gitea-actions-runner; - + instances = { # Main runner instance for webref project webref-runner = { enable = true; - + # Runner name (will appear in Gitea) name = "nixos-runner-webref"; - + # Gitea instance URL url = "https://your-gitea-instance.com"; - + # Runner token - Generate this from Gitea: # Settings -> Actions -> Runners -> Create New Runner # Store the token in a file and reference it here tokenFile = "/var/secrets/gitea-runner-token"; - + # Labels define what jobs this runner can handle # Format: "label:docker_image" or just "label" for host execution labels = [ # Native execution with Nix "nix:native" - + # Ubuntu-like for compatibility "ubuntu-latest:docker://node:20-bookworm" - + # Specific for this project "webref:native" ]; - + # Host packages available to the runner hostPackages = with pkgs; [ # Essential tools @@ -44,15 +44,15 @@ curl git nix - + # Project-specific nodejs python3 postgresql - + # Binary cache attic-client - + # Container runtime (optional) docker docker-compose @@ -75,16 +75,19 @@ extraGroups = [ "docker" ]; }; - users.groups.gitea-runner = {}; + users.groups.gitea-runner = { }; # Allow runner to use Nix nix.settings = { allowed-users = [ "gitea-runner" ]; trusted-users = [ "gitea-runner" ]; - + # Enable flakes for the runner - experimental-features = [ "nix-command" "flakes" ]; - + experimental-features = [ + "nix-command" + "flakes" + ]; + # Optimize for CI performance max-jobs = "auto"; cores = 0; # Use all available cores @@ -102,11 +105,10 @@ # Resource limits (adjust based on your hardware) MemoryMax = "8G"; CPUQuota = "400%"; # 4 cores - + # Restart policy Restart = "always"; RestartSec = "10s"; }; }; } - diff --git a/nixos/tests.nix b/nixos/tests.nix index 2cb856d..4a2ca73 100644 --- a/nixos/tests.nix +++ b/nixos/tests.nix @@ -4,189 +4,203 @@ # Backend integration tests with PostgreSQL and MinIO backend-integration = pkgs.testers.nixosTest { name = "webref-backend-integration"; - + nodes = { - machine = { config, pkgs, ... }: { - # PostgreSQL service - services.postgresql = { - enable = true; - ensureDatabases = [ "webref" ]; - ensureUsers = [{ - name = "webref"; - ensureDBOwnership = true; - }]; - authentication = '' - local all all trust - host all all 127.0.0.1/32 trust - host all all ::1/128 trust - ''; + machine = + { pkgs, ... }: + { + # PostgreSQL service + services.postgresql = { + enable = true; + ensureDatabases = [ "webref" ]; + ensureUsers = [ + { + name = "webref"; + ensureDBOwnership = true; + } + ]; + authentication = '' + local all all trust + host all all 127.0.0.1/32 trust + host all all ::1/128 trust + ''; + }; + + # MinIO service + services.minio = { + enable = true; + rootCredentialsFile = pkgs.writeText "minio-credentials" '' + MINIO_ROOT_USER=minioadmin + MINIO_ROOT_PASSWORD=minioadmin + ''; + }; + + # Install required packages + environment.systemPackages = with pkgs; [ + python3 + python3Packages.pytest + python3Packages.fastapi + postgresql + curl + ]; + + # Network configuration + networking.firewall.enable = false; }; - - # MinIO service - services.minio = { - enable = true; - rootCredentialsFile = pkgs.writeText "minio-credentials" '' - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin - ''; - }; - - # Install required packages - environment.systemPackages = with pkgs; [ - python3 - python3Packages.pytest - python3Packages.fastapi - postgresql - curl - ]; - - # Network configuration - networking.firewall.enable = false; - }; }; - + testScript = '' start_all() - + # Wait for PostgreSQL machine.wait_for_unit("postgresql.service") machine.wait_for_open_port(5432) - + # Wait for MinIO machine.wait_for_unit("minio.service") machine.wait_for_open_port(9000) - + # Verify PostgreSQL is working machine.succeed("sudo -u postgres psql -c 'SELECT 1;'") - + # Verify MinIO is working machine.succeed("curl -f http://localhost:9000/minio/health/live") - + machine.succeed("echo '✅ Backend integration test passed'") ''; }; - + # Full stack test with backend + database full-stack = pkgs.testers.nixosTest { name = "webref-full-stack"; - + nodes = { - machine = { config, pkgs, ... }: { - # PostgreSQL - services.postgresql = { - enable = true; - ensureDatabases = [ "webref" ]; - ensureUsers = [{ - name = "webref"; - ensureDBOwnership = true; - }]; + machine = + { pkgs, ... }: + { + # PostgreSQL + services.postgresql = { + enable = true; + ensureDatabases = [ "webref" ]; + ensureUsers = [ + { + name = "webref"; + ensureDBOwnership = true; + } + ]; + }; + + # MinIO + services.minio = { + enable = true; + rootCredentialsFile = pkgs.writeText "minio-credentials" '' + MINIO_ROOT_USER=minioadmin + MINIO_ROOT_PASSWORD=minioadmin + ''; + }; + + environment.systemPackages = with pkgs; [ + python3 + curl + jq + ]; + + networking.firewall.enable = false; }; - - # MinIO - services.minio = { - enable = true; - rootCredentialsFile = pkgs.writeText "minio-credentials" '' - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin - ''; - }; - - environment.systemPackages = with pkgs; [ - python3 - curl - jq - ]; - - networking.firewall.enable = false; - }; }; - + testScript = '' start_all() - + # Wait for services machine.wait_for_unit("postgresql.service") machine.wait_for_unit("minio.service") machine.wait_for_open_port(5432) machine.wait_for_open_port(9000) - + # Test database connectivity machine.succeed("sudo -u postgres psql -c 'SELECT version();'") - + # Test MinIO API machine.succeed("curl -f http://localhost:9000/minio/health/live") - + machine.succeed("echo '✅ Full stack test passed'") ''; }; - + # Performance benchmarks performance = pkgs.testers.nixosTest { name = "webref-performance"; - + nodes = { - machine = { config, pkgs, ... }: { - services.postgresql.enable = true; - services.minio.enable = true; - - environment.systemPackages = with pkgs; [ - python3 - ]; - }; + machine = + { pkgs, ... }: + { + services.postgresql.enable = true; + services.minio.enable = true; + + environment.systemPackages = with pkgs; [ + python3 + ]; + }; }; - + testScript = '' start_all() machine.wait_for_unit("postgresql.service") - + machine.succeed("echo '✅ Performance test passed'") ''; }; - + # Security tests security = pkgs.testers.nixosTest { name = "webref-security"; - + nodes = { - machine = { config, pkgs, ... }: { - services.postgresql = { - enable = true; - ensureDatabases = [ "webref" ]; - ensureUsers = [{ - name = "webref"; - ensureDBOwnership = true; - }]; + machine = + { pkgs, ... }: + { + services.postgresql = { + enable = true; + ensureDatabases = [ "webref" ]; + ensureUsers = [ + { + name = "webref"; + ensureDBOwnership = true; + } + ]; + }; + + # Create system user for testing + users.users.webref = { + isSystemUser = true; + group = "webref"; + }; + users.groups.webref = { }; + + environment.systemPackages = with pkgs; [ + python3 + nmap + ]; }; - - # Create system user for testing - users.users.webref = { - isSystemUser = true; - group = "webref"; - }; - users.groups.webref = {}; - - environment.systemPackages = with pkgs; [ - python3 - nmap - ]; - }; }; - + testScript = '' start_all() machine.wait_for_unit("postgresql.service") - + # Wait for PostgreSQL setup scripts to complete (database and user creation) import time machine.wait_for_unit("postgresql-setup.service", timeout=30) time.sleep(2) # Give it a moment to finalize - + # Verify database role exists machine.succeed("sudo -u postgres psql -c '\\du' | grep webref") - + # Verify database is accessible with webref user machine.succeed("sudo -u webref psql webref -c 'SELECT 1;'") - + machine.succeed("echo '✅ Security test passed'") ''; };