linux observer
1# solstone-linux Makefile
2# Standalone Linux desktop observer for solstone
3
4.PHONY: install test test-only format ci clean clean-install versions all bootstrap install-service service-restart service-status service-logs uninstall-service
5
6# Default target
7all: install
8
9# Virtual environment directory
10VENV := .venv
11VENV_BIN := $(VENV)/bin
12PYTHON := $(VENV_BIN)/python
13
14# Require uv
15UV := $(shell command -v uv 2>/dev/null)
16ifneq ($(filter bootstrap,$(MAKECMDGOALS)),bootstrap)
17ifndef UV
18$(error uv is not installed. Run: make bootstrap)
19endif
20endif
21
22APP := solstone-linux
23UNIT := solstone-linux.service
24PIPX_FLAGS := --system-site-packages
25VENV_FLAGS := --system-site-packages
26
27# Marker file to track installation
28.installed: pyproject.toml
29 @echo "Installing package with uv (including dev tools)..."
30 @[ -f $(VENV)/pyvenv.cfg ] || $(UV) venv $(VENV_FLAGS) --python /usr/bin/python3 $(VENV)
31 $(UV) sync --group dev --no-install-package pygobject --no-install-package pycairo
32 @touch .installed
33
34# Install package in editable mode with isolated venv
35install: .installed
36
37bootstrap:
38 @if command -v uv >/dev/null 2>&1; then \
39 echo "uv already installed"; \
40 else \
41 echo "installing uv..."; \
42 curl -LsSf https://astral.sh/uv/install.sh | sh; \
43 fi
44 @if ! command -v pipx >/dev/null 2>&1; then \
45 echo "pipx missing — install instructions:"; \
46 echo " fedora: sudo dnf install pipx"; \
47 echo " debian: sudo apt install pipx"; \
48 echo " arch: sudo pacman -S python-pipx"; \
49 echo " opensuse: sudo zypper install python3-pipx"; \
50 exit 1; \
51 fi
52 @python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3,10) else 1)' || { \
53 echo "python >=3.10 required"; exit 1; \
54 }
55 @if [ -f .installed ]; then \
56 $(VENV_BIN)/solstone-linux doctor; \
57 else \
58 echo "now run: make install-service"; \
59 fi
60
61install-service: .installed
62 @$(VENV_BIN)/solstone-linux doctor
63 @command -v pipx >/dev/null || { echo "pipx not found — install with: sudo dnf install pipx (or apt/brew equivalent)"; exit 1; }
64 @$(PYTHON) -m solstone_linux.install_guard preinstall "$(CURDIR)"; rc=$$?; \
65 if [ $$rc -eq 2 ]; then exit 1; \
66 elif [ $$rc -eq 10 ]; then $(MAKE) ci; \
67 fi
68 # Editable installs (pipx install -e .) are deliberately avoided: pipx treats editable installs differently and system-site-packages behavior is unreliable with them.
69 pipx install --force $(PIPX_FLAGS) .
70 $(PYTHON) -m solstone_linux.install_guard write "$(CURDIR)"
71 $(APP) install-service
72 systemctl --user status $(UNIT) --no-pager -l | head -n 20 || true
73
74service-restart:
75 systemctl --user restart $(UNIT)
76
77service-status:
78 systemctl --user --no-pager status $(UNIT)
79
80service-logs:
81 journalctl --user -u $(UNIT) -n 100 --no-pager -f
82
83uninstall-service: .installed
84 @$(PYTHON) -m solstone_linux.install_guard preuninstall "$(CURDIR)"; rc=$$?; \
85 if [ $$rc -eq 2 ]; then exit 1; \
86 elif [ $$rc -eq 0 ]; then exit 0; \
87 fi
88 -systemctl --user stop $(UNIT)
89 -systemctl --user disable $(UNIT)
90 -rm -f $(HOME)/.config/systemd/user/$(UNIT)
91 -systemctl --user daemon-reload
92 -pipx uninstall $(APP)
93 $(PYTHON) -m solstone_linux.install_guard remove
94
95# Venv tool shortcuts
96PYTEST := $(VENV_BIN)/pytest
97RUFF := $(VENV_BIN)/ruff
98
99# Run all tests
100test: .installed
101 @echo "Running tests..."
102 $(PYTEST) tests/ -q
103
104# Run specific test file or pattern
105test-only: .installed
106 @if [ -z "$(TEST)" ]; then \
107 echo "Usage: make test-only TEST=<test_file_or_pattern>"; \
108 echo "Example: make test-only TEST=tests/test_config.py"; \
109 echo "Example: make test-only TEST=\"-k test_function_name\""; \
110 exit 1; \
111 fi
112 $(PYTEST) $(TEST)
113
114# Auto-format and fix code, then report remaining issues
115format: .installed
116 @echo "Formatting and fixing code with ruff..."
117 @$(RUFF) format .
118 @$(RUFF) check --fix .
119 @echo ""
120 @echo "Checking for remaining issues..."
121 @$(RUFF) check . || { echo ""; echo "Issues above need manual fixes."; exit 1; }
122 @echo ""
123 @echo "All clean!"
124
125# Run CI checks (what CI would run)
126ci: .installed
127 @echo "Running CI checks..."
128 @echo "=== Checking formatting ==="
129 @$(RUFF) format --check . || { echo "Run 'make format' to fix formatting"; exit 1; }
130 @echo ""
131 @echo "=== Running ruff ==="
132 @$(RUFF) check . || { echo "Run 'make format' to auto-fix"; exit 1; }
133 @echo ""
134 @echo "=== Running tests ==="
135 @$(MAKE) test
136 @echo ""
137 @echo "All CI checks passed!"
138
139# Clean build artifacts and cache files
140clean:
141 @echo "Cleaning build artifacts and cache files..."
142 rm -rf build/ dist/ *.egg-info/
143 rm -rf .pytest_cache/ .mypy_cache/
144 find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
145 find . -type f -name "*.pyc" -delete
146 find . -type f -name "*.pyo" -delete
147 rm -f .installed
148 rm -rf $(VENV)
149
150# Clean everything and reinstall
151clean-install: clean install
152
153# Show installed package versions
154versions: .installed
155 @echo "=== Python version ==="
156 $(PYTHON) --version
157 @echo ""
158 @echo "=== Installed packages ==="
159 @$(UV) pip list | grep -E "^(pytest|ruff|requests|numpy|soundfile|soundcard|dbus-next|PyGObject)" || true