forked from enviPath/enviPy
Update commands to automatically run pnpm for relevant commands
Signed-off-by: Tobias O <tobias.olenyi@tum.de>
This commit is contained in:
67
epdb/management/commands/collectstatic.py
Normal file
67
epdb/management/commands/collectstatic.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
"""
|
||||||
|
Custom collectstatic command that automatically builds CSS first.
|
||||||
|
Overrides Django's default collectstatic to include pnpm build.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.staticfiles.management.commands.collectstatic import (
|
||||||
|
Command as CollectstaticCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Command(CollectstaticCommand):
|
||||||
|
help = "Collect static files (automatically builds CSS first)"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""Build CSS before collecting static files."""
|
||||||
|
self.stdout.write(self.style.SUCCESS("Building CSS with pnpm..."))
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Run pnpm build
|
||||||
|
result = subprocess.run(
|
||||||
|
["pnpm", "run", "build"],
|
||||||
|
cwd=settings.BASE_DIR,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=60, # 60 second timeout
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
self.stdout.write(self.style.ERROR("✗ CSS build failed:"))
|
||||||
|
self.stdout.write(result.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verify output.css was created
|
||||||
|
output_css = Path(settings.BASE_DIR) / "static" / "css" / "output.css"
|
||||||
|
if not output_css.exists():
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.ERROR("✗ CSS build failed: output.css not generated")
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Show file size
|
||||||
|
size_kb = output_css.stat().st_size / 1024
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(f"✓ CSS built successfully ({size_kb:.1f}KB)\n")
|
||||||
|
)
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.ERROR(
|
||||||
|
"✗ Error: pnpm not found. Install pnpm to build CSS.\n"
|
||||||
|
"See README.md for setup instructions."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
self.stdout.write(self.style.ERROR("✗ CSS build timed out (>60s)"))
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
self.stdout.write(self.style.ERROR(f"✗ CSS build error: {e}"))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Run normal collectstatic
|
||||||
|
super().handle(*args, **options)
|
||||||
81
epdb/management/commands/runserver.py
Normal file
81
epdb/management/commands/runserver.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
Custom runserver command that automatically starts CSS watcher.
|
||||||
|
Overrides Django's default runserver to include pnpm dev.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.staticfiles.management.commands.runserver import (
|
||||||
|
Command as RunserverCommand,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Command(RunserverCommand):
|
||||||
|
help = "Run development server with automatic CSS building"
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.css_process = None
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""Start CSS watcher before running Django dev server."""
|
||||||
|
self.stdout.write(self.style.SUCCESS("Starting CSS watcher (pnpm dev)..."))
|
||||||
|
|
||||||
|
# Start pnpm dev in background
|
||||||
|
try:
|
||||||
|
self.css_process = subprocess.Popen(
|
||||||
|
["pnpm", "run", "dev"],
|
||||||
|
cwd=settings.BASE_DIR,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
self.stdout.write(self.style.SUCCESS("✓ CSS watcher started\n"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.WARNING(
|
||||||
|
"Warning: pnpm not found. CSS will not be rebuilt automatically.\n"
|
||||||
|
'Install pnpm or run "pnpm run dev" manually in another terminal.\n'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.WARNING(f"Warning: Could not start CSS watcher: {e}\n")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Register cleanup handler
|
||||||
|
original_sigint = signal.getsignal(signal.SIGINT)
|
||||||
|
original_sigterm = signal.getsignal(signal.SIGTERM)
|
||||||
|
|
||||||
|
def cleanup(signum, frame):
|
||||||
|
self.stdout.write("\nShutting down...")
|
||||||
|
if self.css_process:
|
||||||
|
self.css_process.terminate()
|
||||||
|
try:
|
||||||
|
self.css_process.wait(timeout=5)
|
||||||
|
self.stdout.write(self.style.SUCCESS("✓ CSS watcher stopped"))
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
self.css_process.kill()
|
||||||
|
# Call original handler
|
||||||
|
if signum == signal.SIGINT and callable(original_sigint):
|
||||||
|
original_sigint(signum, frame)
|
||||||
|
elif signum == signal.SIGTERM and callable(original_sigterm):
|
||||||
|
original_sigterm(signum, frame)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, cleanup)
|
||||||
|
signal.signal(signal.SIGTERM, cleanup)
|
||||||
|
|
||||||
|
# Run Django dev server
|
||||||
|
try:
|
||||||
|
super().handle(*args, **options)
|
||||||
|
finally:
|
||||||
|
# Cleanup on normal exit
|
||||||
|
if self.css_process:
|
||||||
|
self.css_process.terminate()
|
||||||
|
try:
|
||||||
|
self.css_process.wait(timeout=5)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
self.css_process.kill()
|
||||||
Reference in New Issue
Block a user