Refactor CI/CD workflow to utilize NixOS VM for testing
Some checks failed
Test Suite / test (push) Failing after 16s
Some checks failed
Test Suite / test (push) Failing after 16s
- Changed the CI workflow to run tests inside a NixOS virtual machine instead of directly on the runner. - Updated the NixOS VM configuration to include necessary dependencies and services for testing. - Added a script to handle test execution within the VM, including setup for Python and Node.js environments. - Implemented SSH access to the VM for remote operations and streamlined the process of starting and stopping the VM during tests. - Enhanced the workflow to build the VM and copy the codebase for testing, ensuring a more isolated and consistent testing environment.
This commit is contained in:
@@ -8,90 +8,84 @@ on:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: nixos
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Nix
|
||||
uses: cachix/install-nix-action@v20
|
||||
with:
|
||||
nix: 2.18.1
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
|
||||
- name: Install Nix dependencies
|
||||
- name: Build NixOS VM
|
||||
run: |
|
||||
nix profile install nixpkgs#postgresql
|
||||
nix profile install nixpkgs#python3
|
||||
nix profile install nixpkgs#nodejs_20
|
||||
nix profile install nixpkgs#npm
|
||||
# Build the VM configuration using nixos-rebuild
|
||||
# This creates a VM that can be run with QEMU
|
||||
nixos-rebuild build-vm \
|
||||
-I nixos-config=./nix/test-vm.nix \
|
||||
-I nixpkgs=<nixpkgs> \
|
||||
-o vm-result
|
||||
|
||||
- name: Setup Python
|
||||
- name: Start VM
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
pip install -r backend/requirements.txt
|
||||
# Find the VM run script (name may vary)
|
||||
VM_SCRIPT=$(find vm-result/bin -name "run-*-vm" -type f | head -1)
|
||||
if [ -z "$VM_SCRIPT" ]; then
|
||||
echo "VM script not found in vm-result/bin"
|
||||
ls -la vm-result/bin/
|
||||
exit 1
|
||||
fi
|
||||
echo "Starting VM with script: $VM_SCRIPT"
|
||||
|
||||
- name: Setup Node.js
|
||||
# Start VM in background
|
||||
# The VM will expose SSH on port 2222
|
||||
$VM_SCRIPT > vm.log 2>&1 &
|
||||
VM_PID=$!
|
||||
echo "VM_PID=$VM_PID" >> $GITHUB_ENV
|
||||
|
||||
# Wait for VM to boot and SSH to be available
|
||||
echo "Waiting for VM to boot..."
|
||||
for i in {1..120}; do
|
||||
if ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=2 \
|
||||
-p 2222 root@127.0.0.1 "echo 'VM is ready'" 2>/dev/null; then
|
||||
echo "VM is ready!"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 120 ]; then
|
||||
echo "VM failed to start after 4 minutes"
|
||||
echo "VM log:"
|
||||
tail -100 vm.log
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
- name: Copy code to VM
|
||||
run: |
|
||||
cd frontend
|
||||
npm ci
|
||||
# Copy the entire repository to the VM
|
||||
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222"
|
||||
ssh $SSH_OPTS root@127.0.0.1 "mkdir -p /tmp/moviemap"
|
||||
|
||||
- name: Start PostgreSQL
|
||||
# Use tar to copy files (more reliable than rsync in CI)
|
||||
tar --exclude='.git' \
|
||||
--exclude='node_modules' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='*.pyc' \
|
||||
--exclude='.pytest_cache' \
|
||||
--exclude='dist' \
|
||||
--exclude='vm-result' \
|
||||
-czf - . | ssh $SSH_OPTS root@127.0.0.1 "cd /tmp/moviemap && tar -xzf -"
|
||||
|
||||
- name: Run all tests in VM
|
||||
run: |
|
||||
sudo systemctl start postgresql || sudo service postgresql start
|
||||
sudo -u postgres psql -c "CREATE DATABASE moviemap_test;"
|
||||
sudo -u postgres psql -c "CREATE USER moviemap WITH PASSWORD 'test';"
|
||||
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE moviemap_test TO moviemap;"
|
||||
sudo -u postgres psql -c "ALTER USER moviemap CREATEDB;"
|
||||
env:
|
||||
POSTGRES_HOST: localhost
|
||||
POSTGRES_PORT: 5432
|
||||
# Execute the test script inside the VM
|
||||
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p 2222"
|
||||
ssh $SSH_OPTS root@127.0.0.1 "bash /tmp/moviemap/scripts/run-tests-in-vm.sh"
|
||||
|
||||
- name: Run database migrations
|
||||
run: |
|
||||
cd backend
|
||||
export POSTGRES_SOCKET_PATH=/var/run/postgresql
|
||||
export POSTGRES_DB=moviemap_test
|
||||
export POSTGRES_USER=moviemap
|
||||
alembic upgrade head
|
||||
env:
|
||||
TEST_POSTGRES_DB: moviemap_test
|
||||
TEST_POSTGRES_USER: moviemap
|
||||
TEST_POSTGRES_SOCKET_PATH: /var/run/postgresql
|
||||
|
||||
- name: Run backend tests
|
||||
run: |
|
||||
cd backend
|
||||
export POSTGRES_SOCKET_PATH=/var/run/postgresql
|
||||
export POSTGRES_DB=moviemap_test
|
||||
export POSTGRES_USER=moviemap
|
||||
export TEST_POSTGRES_DB=moviemap_test
|
||||
export TEST_POSTGRES_USER=moviemap
|
||||
export TEST_POSTGRES_SOCKET_PATH=/var/run/postgresql
|
||||
pytest tests/ -v --cov=app --cov-report=term-missing
|
||||
env:
|
||||
# Mock *arr URLs for testing (tests will mock the actual API calls)
|
||||
RADARR_URL: http://localhost:7878
|
||||
SONARR_URL: http://localhost:8989
|
||||
LIDARR_URL: http://localhost:8686
|
||||
RADARR_API_KEY: test-key
|
||||
SONARR_API_KEY: test-key
|
||||
LIDARR_API_KEY: test-key
|
||||
|
||||
- name: Build frontend
|
||||
run: |
|
||||
cd frontend
|
||||
npm run build
|
||||
|
||||
- name: Run frontend tests
|
||||
run: |
|
||||
cd frontend
|
||||
npm test -- --run
|
||||
|
||||
- name: Cleanup
|
||||
- name: Stop VM
|
||||
if: always()
|
||||
run: |
|
||||
sudo systemctl stop postgresql || sudo service postgresql stop || true
|
||||
if [ ! -z "$VM_PID" ]; then
|
||||
kill $VM_PID || true
|
||||
wait $VM_PID 2>/dev/null || true
|
||||
fi
|
||||
# Also try to kill any remaining QEMU processes
|
||||
pkill -f "moviemap-test-vm" || true
|
||||
|
||||
|
||||
116
nix/test-vm.nix
116
nix/test-vm.nix
@@ -1,12 +1,20 @@
|
||||
# NixOS VM configuration for testing Movie Map
|
||||
# This VM includes PostgreSQL, Radarr, Sonarr, and Lidarr with test data
|
||||
# NixOS VM configuration for testing Movie Map in CI/CD
|
||||
# This VM includes all dependencies needed for testing
|
||||
# Usage: nixos-rebuild build-vm -I nixos-config=./nix/test-vm.nix
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Enable QEMU guest agent for better VM management
|
||||
services.qemuGuest.enable = true;
|
||||
imports = [
|
||||
<nixpkgs/nixos/modules/virtualisation/qemu-vm.nix>
|
||||
];
|
||||
|
||||
# VM-specific configuration
|
||||
virtualisation = {
|
||||
memorySize = 2048; # 2GB RAM
|
||||
cores = 2;
|
||||
graphics = false; # Headless
|
||||
};
|
||||
|
||||
# Networking - allow external access
|
||||
networking = {
|
||||
hostName = "moviemap-test-vm";
|
||||
firewall = {
|
||||
@@ -14,13 +22,23 @@
|
||||
allowedTCPPorts = [
|
||||
8080 # Movie Map backend
|
||||
5432 # PostgreSQL
|
||||
7878 # Radarr
|
||||
8989 # Sonarr
|
||||
8686 # Lidarr
|
||||
22 # SSH
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Enable SSH for remote access
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PermitRootLogin = "yes";
|
||||
PasswordAuthentication = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Set root password for SSH access
|
||||
users.users.root.password = "test";
|
||||
|
||||
# PostgreSQL configuration
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
@@ -40,63 +58,35 @@
|
||||
};
|
||||
};
|
||||
|
||||
# Radarr configuration
|
||||
services.radarr = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "radarr";
|
||||
group = "radarr";
|
||||
};
|
||||
|
||||
# Sonarr configuration
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "sonarr";
|
||||
group = "sonarr";
|
||||
};
|
||||
|
||||
# Lidarr configuration
|
||||
services.lidarr = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "lidarr";
|
||||
group = "lidarr";
|
||||
};
|
||||
|
||||
# Create test API keys for *arr services
|
||||
# These will be set via environment variables in the CI/CD
|
||||
# For now, we'll create a script that generates them
|
||||
systemd.services.setup-arr-services = {
|
||||
description = "Setup *arr services with test API keys";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "radarr.service" "sonarr.service" "lidarr.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script = ''
|
||||
# Wait for services to be ready
|
||||
sleep 10
|
||||
|
||||
# Note: In a real setup, you would configure API keys via the *arr APIs
|
||||
# For testing, we'll use environment variables set by CI/CD
|
||||
echo "Test VM setup complete"
|
||||
'';
|
||||
};
|
||||
|
||||
# Environment variables for test configuration
|
||||
environment.variables = {
|
||||
TEST_RADARR_URL = "http://localhost:7878";
|
||||
TEST_SONARR_URL = "http://localhost:8989";
|
||||
TEST_LIDARR_URL = "http://localhost:8686";
|
||||
};
|
||||
|
||||
# System packages
|
||||
# Python and Node.js for testing
|
||||
environment.systemPackages = with pkgs; [
|
||||
python3
|
||||
python3Packages.pip
|
||||
nodejs_20
|
||||
nodePackages.npm
|
||||
postgresql
|
||||
curl
|
||||
jq
|
||||
postgresql
|
||||
git
|
||||
vim
|
||||
# Testing tools
|
||||
python3Packages.pytest
|
||||
python3Packages.pytest-asyncio
|
||||
python3Packages.pytest-cov
|
||||
python3Packages.httpx
|
||||
];
|
||||
}
|
||||
|
||||
# Create a test user
|
||||
users.users.test = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
password = "test";
|
||||
openssh.authorizedKeys.keys = [];
|
||||
};
|
||||
|
||||
# Allow passwordless sudo for test user
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
# System configuration
|
||||
system.stateVersion = "23.11";
|
||||
}
|
||||
|
||||
9
nix/vm-config.nix
Normal file
9
nix/vm-config.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
# VM configuration entry point for CI/CD
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./test-vm.nix
|
||||
];
|
||||
}
|
||||
|
||||
64
scripts/run-tests-in-vm.sh
Executable file
64
scripts/run-tests-in-vm.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
# Helper script to run tests inside the VM
|
||||
# This script is executed inside the VM
|
||||
|
||||
set -e
|
||||
|
||||
cd /tmp/moviemap
|
||||
|
||||
echo "=== Setting up test environment ==="
|
||||
|
||||
# Setup Python
|
||||
cd backend
|
||||
export PATH="/root/.local/bin:$PATH"
|
||||
python3 -m pip install --user --upgrade pip
|
||||
python3 -m pip install --user -r requirements.txt
|
||||
|
||||
# Setup Node.js
|
||||
cd ../frontend
|
||||
npm ci
|
||||
|
||||
echo "=== Waiting for PostgreSQL ==="
|
||||
# Wait for PostgreSQL to be ready
|
||||
for i in {1..30}; do
|
||||
if sudo -u postgres psql -c "SELECT 1;" > /dev/null 2>&1; then
|
||||
echo "PostgreSQL is ready"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo "PostgreSQL failed to start"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "=== Running database migrations ==="
|
||||
cd ../backend
|
||||
export POSTGRES_SOCKET_PATH=/var/run/postgresql
|
||||
export POSTGRES_DB=moviemap_test
|
||||
export POSTGRES_USER=moviemap
|
||||
export PATH="/root/.local/bin:$PATH"
|
||||
alembic upgrade head
|
||||
|
||||
echo "=== Running backend tests ==="
|
||||
export TEST_POSTGRES_DB=moviemap_test
|
||||
export TEST_POSTGRES_USER=moviemap
|
||||
export TEST_POSTGRES_SOCKET_PATH=/var/run/postgresql
|
||||
export RADARR_URL=http://localhost:7878
|
||||
export SONARR_URL=http://localhost:8989
|
||||
export LIDARR_URL=http://localhost:8686
|
||||
export RADARR_API_KEY=test-key
|
||||
export SONARR_API_KEY=test-key
|
||||
export LIDARR_API_KEY=test-key
|
||||
export PATH="/root/.local/bin:$PATH"
|
||||
pytest tests/ -v --cov=app --cov-report=term-missing
|
||||
|
||||
echo "=== Building frontend ==="
|
||||
cd ../frontend
|
||||
npm run build
|
||||
|
||||
echo "=== Running frontend tests ==="
|
||||
npm test -- --run
|
||||
|
||||
echo "=== All tests completed successfully ==="
|
||||
|
||||
Reference in New Issue
Block a user