-
Notifications
You must be signed in to change notification settings - Fork 154
Expand file tree
/
Copy pathMakefile
More file actions
716 lines (664 loc) · 25.1 KB
/
Makefile
File metadata and controls
716 lines (664 loc) · 25.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# Voice MCP Makefile
.PHONY: help install dev-install clean \
build build-package build-installer build-dev \
test test-package test-all test-unit test-integration test-parallel test-markers \
coverage coverage-html coverage-xml \
publish publish-package publish-installer \
publish-test publish-package-test publish-installer-test \
release release-package release-installer \
docs-serve docs-build docs-check docs-deploy \
clean-dist clean-package clean-installer \
test-installer-ubuntu test-installer-fedora test-installer-all test-installer-ci \
test-installer-pypi test-installer-pypi-ubuntu test-installer-pypi-fedora \
test-installer-pypi-all \
vm-ubuntu vm-fedora vm-macos vm-ubuntu-quick vm-fedora-quick vm-macos-quick vm-clean vm-list
# Default target
help:
@echo "Voice MCP Build Targets:"
@echo ""
@echo "Development:"
@echo " install - Install package in normal mode"
@echo " dev-install - Install package in editable mode with dev dependencies"
@echo " clean - Remove all build artifacts and caches"
@echo ""
@echo "Testing:"
@echo " test - Run unit tests with pytest"
@echo " test-unit - Run unit tests only"
@echo " test-integration - Run integration tests"
@echo " test-all - Run all tests (including slow/manual)"
@echo " test-parallel - Run tests in parallel"
@echo " test-markers - Show available test markers"
@echo ""
@echo "Coverage:"
@echo " coverage - Run tests with coverage report"
@echo " coverage-html - Generate and open HTML coverage report"
@echo " coverage-xml - Generate XML coverage report (for CI)"
@echo ""
@echo "Building:"
@echo " build - Build both packages"
@echo " build-package - Build voice-mode package only"
@echo " build-installer - Build voice-mode-install package only"
@echo " build-dev - Build development package with auto-versioning"
@echo " test-package - Test package installation"
@echo ""
@echo "Publishing to PyPI:"
@echo " publish - Publish both packages to PyPI"
@echo " publish-package - Publish voice-mode package to PyPI"
@echo " publish-installer - Publish voice-mode-install to PyPI"
@echo ""
@echo "Publishing to TestPyPI:"
@echo " publish-test - Publish both packages to TestPyPI"
@echo " publish-package-test - Publish voice-mode to TestPyPI"
@echo " publish-installer-test - Publish voice-mode-install to TestPyPI"
@echo ""
@echo "Release Management:"
@echo " release - Create unified release for both packages"
@echo " release-package - Release voice-mode package only"
@echo " release-installer - Release voice-mode-install package only"
@echo ""
@echo "Installer Testing (Local Build):"
@echo " test-installer-ubuntu - Test on fresh Ubuntu clone"
@echo " test-installer-fedora - Test on fresh Fedora clone"
@echo " test-installer-all - Test on fresh clones of all platforms"
@echo " test-installer-ci - Test installer using Docker"
@echo ""
@echo "Installer Testing (From PyPI):"
@echo " test-installer-pypi - Test latest from PyPI (all platforms)"
@echo " test-installer-pypi-ubuntu - Test latest from PyPI on Ubuntu"
@echo " test-installer-pypi-fedora - Test latest from PyPI on Fedora"
@echo " test-installer-pypi-all - Test latest from PyPI (fresh clones)"
@echo ""
@echo "Documentation:"
@echo " docs-serve - Serve documentation locally (http://localhost:8000)"
@echo " docs-build - Build documentation site"
@echo " docs-check - Check documentation for errors (strict mode)"
@echo " docs-deploy - Deploy to ReadTheDocs (requires auth)"
@echo ""
@echo "Manual VM Testing:"
@echo " vm-ubuntu - Start fresh Ubuntu VM and show SSH command"
@echo " vm-fedora - Start fresh Fedora VM and show SSH command"
@echo " vm-macos - Start fresh macOS VM and show SSH command"
@echo " vm-ubuntu-quick - Start persistent Ubuntu VM (faster)"
@echo " vm-fedora-quick - Start persistent Fedora VM (faster)"
@echo " vm-macos-quick - Start persistent macOS VM (faster)"
@echo " vm-clean - Clean up persistent VMs"
@echo " vm-list - List all Tart VMs"
# Install package
install:
@echo "Installing voice-mode..."
uv pip install -e .
@echo "Installation complete!"
# Install package with development dependencies
dev-install:
@echo "Installing voice-mode with development dependencies..."
uv pip install -e ".[dev,test]"
@echo "Development installation complete!"
# Build Python package
build-package:
@echo "Building voice-mode package..."
@uv build
@echo "✅ Package built: dist/"
@ls -lh dist/
# Build development package with auto-versioning
build-dev:
@echo "Building development package..."
@# Save current version
@cp voice_mode/__version__.py voice_mode/__version__.py.bak
@# Get current version and append .dev suffix with timestamp
@CURRENT_VERSION=$$(uv run python -c "exec(open('voice_mode/__version__.py').read()); print(__version__)") && \
DEV_VERSION="$$CURRENT_VERSION.dev$$(date +%Y%m%d%H%M%S)" && \
echo "__version__ = \"$$DEV_VERSION\"" > voice_mode/__version__.py && \
echo "Building version $$DEV_VERSION..." && \
uv build || (mv voice_mode/__version__.py.bak voice_mode/__version__.py; exit 1)
@# Restore original version
@mv voice_mode/__version__.py.bak voice_mode/__version__.py
@echo "Development package built successfully in dist/"
# Run unit tests
test:
@echo "Running unit tests..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@echo "Running tests..."
@uv run pytest tests/ -v --tb=short
@echo "Tests completed!"
# Test package installation (FIXED: Now uses UV)
test-package: build-package
@echo "Testing package installation..."
@cd /tmp && \
uv venv test-env && \
. test-env/bin/activate && \
uv pip install $(CURDIR)/dist/voice_mode-*.whl && \
voice-mode --help && \
deactivate && \
rm -rf test-env
@echo "Package test successful!"
# Publish to TestPyPI - unified target for both packages
publish-test: clean-dist build
@echo "Publishing both packages to TestPyPI..."
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
echo "Get a token from https://test.pypi.org/manage/account/token/"; \
echo "Then set: export UV_PUBLISH_TOKEN=\"pypi-your-test-token\""; \
exit 1; \
fi
@uv publish --index-url https://test.pypi.org/legacy/
@cd installer && uv publish --index-url https://test.pypi.org/legacy/
@echo "✅ Both packages published to TestPyPI!"
# Publish voice-mode package to TestPyPI
publish-package-test:
@echo "Cleaning voice-mode dist..."
@rm -rf dist/*.whl dist/*.tar.gz
@$(MAKE) build-package
@echo "Publishing voice-mode to TestPyPI..."
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
echo "Get a token from https://test.pypi.org/manage/account/token/"; \
echo "Then set: export UV_PUBLISH_TOKEN=\"pypi-your-test-token\""; \
exit 1; \
fi
@uv publish --index-url https://test.pypi.org/legacy/
@echo "✅ Published to TestPyPI!"
# Publish to PyPI - unified target for both packages
publish: clean-dist build
@echo "Publishing both packages to PyPI..."
@echo ""
@echo "⚠️ WARNING: This will publish BOTH packages to PRODUCTION PyPI!"
@read -p "Are you sure? Type 'yes' to continue: " confirm; \
if [ "$$confirm" != "yes" ]; then \
echo "Aborted."; \
exit 1; \
fi
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
echo "Get a token from https://pypi.org/manage/account/token/"; \
echo "Then set: export UV_PUBLISH_TOKEN=\"pypi-your-token\""; \
exit 1; \
fi
@echo ""
@echo "Publishing voice-mode..."
@uv publish
@echo "✅ voice-mode published!"
@echo ""
@echo "Publishing voice-mode-install..."
@cd installer && uv publish
@echo "✅ voice-mode-install published!"
# Publish voice-mode package only
publish-package:
@echo "Cleaning voice-mode dist..."
@rm -rf dist/*.whl dist/*.tar.gz
@$(MAKE) build-package
@echo "Publishing voice-mode to PyPI..."
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
exit 1; \
fi
@uv publish
@echo "✅ voice-mode published!"
# Publish voice-mode-install package only
publish-installer:
@echo "Cleaning installer dist..."
@rm -rf installer/dist/*.whl installer/dist/*.tar.gz
@$(MAKE) build-installer
@echo "Publishing voice-mode-install to PyPI..."
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
exit 1; \
fi
@cd installer && uv publish
@echo "✅ voice-mode-install published!"
# Clean build artifacts - Three-tier approach for flexibility
clean:
@echo "Cleaning all build artifacts..."
@$(MAKE) clean-package
@$(MAKE) clean-installer
@echo "✅ All build artifacts cleaned!"
clean-package:
@echo "Cleaning voice-mode build artifacts..."
@rm -rf dist/ build/ *.egg-info .pytest_cache __pycache__
@rm -rf htmlcov/ .coverage coverage.xml .coverage.*
@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
@find . -type f -name "*.pyc" -delete
clean-installer:
@echo "Cleaning voice-mode-install build artifacts..."
@rm -rf installer/dist/*.whl installer/dist/*.tar.gz
# Clean only distribution artifacts (for publish safety)
clean-dist:
@echo "Cleaning distribution artifacts..."
@rm -rf dist/*.whl dist/*.tar.gz
@rm -rf installer/dist/*.whl installer/dist/*.tar.gz
@echo "✅ Distribution artifacts cleaned!"
# Release targets - Create a new release and tag
release:
@echo "Creating unified release for voice-mode and voice-mode-install..."
@echo ""
@echo "Current version: $$(uv run python scripts/release.py --current)"
@echo ""
@read -p "Enter new version (e.g., 5.1.5): " version; \
if [ -z "$$version" ]; then \
echo "Error: Version cannot be empty"; \
exit 1; \
fi; \
uv run python scripts/release.py $$version
release-package:
@echo "Creating release for voice-mode package only..."
@echo ""
@echo "Current version: $$(uv run python scripts/release.py --current)"
@echo ""
@read -p "Enter new version (e.g., 5.1.5): " version; \
if [ -z "$$version" ]; then \
echo "Error: Version cannot be empty"; \
exit 1; \
fi; \
uv run python scripts/release.py $$version --package package
release-installer:
@echo "Creating release for voice-mode-install package only..."
@echo ""
@echo "Current version: $$(uv run python scripts/release.py --current)"
@echo ""
@read -p "Enter new version (e.g., 5.1.5): " version; \
if [ -z "$$version" ]; then \
echo "Error: Version cannot be empty"; \
exit 1; \
fi; \
uv run python scripts/release.py $$version --package installer
# Documentation targets (FIXED: Now uses uv run python)
docs-serve:
@echo "Starting documentation server at http://localhost:8000..."
@echo ""
@# Install docs dependencies using uv
@echo "Installing documentation dependencies..."
@uv pip install -e ".[docs]"
@# Process README for docs
@uv run python scripts/process-readme-for-docs.py README.md docs/README_PROCESSED.md
@echo "Press Ctrl+C to stop the server"
@.venv/bin/mkdocs serve
docs-build:
@echo "Building documentation site..."
@# Install docs dependencies using uv
@echo "Installing documentation dependencies..."
@uv pip install -e ".[docs]"
@# Process README for docs
@uv run python scripts/process-readme-for-docs.py README.md docs/README_PROCESSED.md
@.venv/bin/mkdocs build
@echo "Documentation built to site/ directory"
docs-check:
@echo "Checking documentation for errors..."
@# Install docs dependencies using uv
@echo "Installing documentation dependencies..."
@uv pip install -e ".[docs]"
@# Process README for docs
@uv run python scripts/process-readme-for-docs.py README.md docs/README_PROCESSED.md
@echo ""
@echo "Running strict documentation check..."
@.venv/bin/mkdocs build --strict
docs-deploy:
@echo "Deploying documentation to ReadTheDocs..."
@echo "Note: This requires ReadTheDocs authentication"
@# ReadTheDocs typically auto-builds from GitHub
@echo "Push to main branch to trigger ReadTheDocs build"
@echo "Or configure manual deployment in ReadTheDocs dashboard"
# Run tests with coverage report
coverage:
@echo "Running tests with coverage..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@echo "Running tests with coverage..."
@uv run pytest tests --cov --cov-report=html --cov-report=term
@echo ""
@echo "✅ Coverage report generated!"
@echo " Terminal report shown above"
@echo " HTML report: htmlcov/index.html"
@echo ""
@echo "Opening HTML coverage report..."
@open htmlcov/index.html 2>/dev/null || xdg-open htmlcov/index.html 2>/dev/null || echo "Please open htmlcov/index.html manually"
# Generate HTML coverage report
coverage-html: coverage
@echo "Opening coverage report in browser..."
@open htmlcov/index.html 2>/dev/null || xdg-open htmlcov/index.html 2>/dev/null || echo "Please open htmlcov/index.html manually"
# Generate XML coverage report for CI
coverage-xml:
@echo "Generating XML coverage report..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@uv run pytest tests --cov --cov-report=xml
@echo "XML coverage report generated: coverage.xml"
# Run unit tests only
test-unit:
@echo "Running unit tests..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@uv run pytest tests -v -m "unit or not integration"
# Run integration tests only
test-integration:
@echo "Running integration tests..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@uv run pytest tests -v -m "integration"
# Run all tests (including slow and manual)
test-all:
@echo "Running all tests..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@echo "Installing test dependencies..."
@uv pip install -e ".[test]" -q
@uv run pytest tests -v
# Run tests in parallel (requires pytest-xdist)
test-parallel:
@echo "Installing pytest-xdist..."
@if [ ! -d ".venv" ]; then \
echo "Creating virtual environment..."; \
uv venv; \
fi
@uv pip install -e ".[test]" -q
@uv pip install pytest-xdist -q
@echo "Running tests in parallel..."
@uv run pytest tests -n auto -v
# Show available test markers
test-markers:
@echo "Available test markers:"
@echo " unit - Fast, isolated unit tests"
@echo " integration - Tests that interact with services"
@echo " slow - Tests that take > 1s"
@echo " manual - Tests requiring human interaction"
@echo ""
@echo "Usage: uv run pytest -m 'marker_name'"
@echo "Example: uv run pytest -m 'not slow'"
# Build voice-mode-install package (always clean first to prevent old artifacts)
build-installer: clean-installer
@echo "Syncing dependencies.yaml to installer..."
@bash scripts/sync-dependencies.sh
@echo "Building voice-mode-install package..."
@cd installer && uv build
@echo "✅ Package built: installer/dist/"
@ls -lh installer/dist/
# Unified build target for both packages
build: build-package build-installer
@echo "✅ Both packages built successfully!"
# Run installer locally to preview logo and output
run-installer:
@echo "Running voice-mode-install from source..."
@cd installer && uv run voice-mode-install --dry-run --non-interactive 2>&1 | head -30 || true
# Test installer on fresh Ubuntu clone (default)
test-installer-ubuntu: build-installer
@echo "Testing installer on fresh Ubuntu clone..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@WHEEL=$$(ls -t installer/dist/voice_mode_install-*.whl | head -1); \
if [ -z "$$WHEEL" ]; then \
echo "❌ Wheel file not found. Run 'make build-installer' first."; \
exit 1; \
fi; \
echo "Using wheel: $$WHEEL"; \
uv run python scripts/test_installer.py ubuntu --wheel "$$WHEEL" --backend tart --clone-fresh
# Test installer on fresh Fedora clone (default)
test-installer-fedora: build-installer
@echo "Testing installer on fresh Fedora clone..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@WHEEL=$$(ls -t installer/dist/voice_mode_install-*.whl | head -1); \
if [ -z "$$WHEEL" ]; then \
echo "❌ Wheel file not found. Run 'make build-installer' first."; \
exit 1; \
fi; \
echo "Using wheel: $$WHEEL"; \
uv run python scripts/test_installer.py fedora --wheel "$$WHEEL" --backend tart --clone-fresh
# Test installer on fresh clones of all platforms (default)
test-installer-all: build-installer
@echo "Testing installer on fresh clones of all platforms..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@WHEEL=$$(ls -t installer/dist/voice_mode_install-*.whl | head -1); \
if [ -z "$$WHEEL" ]; then \
echo "❌ Wheel file not found. Run 'make build-installer' first."; \
exit 1; \
fi; \
echo "Using wheel: $$WHEEL"; \
echo ""; \
echo "=== Testing Ubuntu (fresh clone) ==="; \
uv run python scripts/test_installer.py ubuntu --wheel "$$WHEEL" --backend tart --clone-fresh || true; \
echo ""; \
echo "=== Testing Fedora (fresh clone) ==="; \
uv run python scripts/test_installer.py fedora --wheel "$$WHEEL" --backend tart --clone-fresh || true
# Test installer using Docker (CI mode)
test-installer-ci: build-installer
@echo "Testing installer with Docker..."
@if ! command -v docker >/dev/null 2>&1; then \
echo "❌ Docker is not installed!"; \
exit 1; \
fi
@WHEEL=$$(ls -t installer/dist/voice_mode_install-*.whl | head -1); \
if [ -z "$$WHEEL" ]; then \
echo "❌ Wheel file not found. Run 'make build-installer' first."; \
exit 1; \
fi; \
echo "Using wheel: $$WHEEL"; \
echo ""; \
echo "=== Testing Ubuntu (Docker) ==="; \
uv run python scripts/test_installer.py ubuntu --wheel "$$WHEEL" --backend docker || true; \
echo ""; \
echo "=== Testing Fedora (Docker) ==="; \
uv run python scripts/test_installer.py fedora --wheel "$$WHEEL" --backend docker || true
# Publish voice-mode-install to TestPyPI
publish-installer-test:
@echo "Cleaning installer dist..."
@rm -rf installer/dist/*.whl installer/dist/*.tar.gz
@$(MAKE) build-installer
@echo "Publishing voice-mode-install to TestPyPI..."
@if [ -z "$$UV_PUBLISH_TOKEN" ]; then \
echo "❌ UV_PUBLISH_TOKEN not set!"; \
echo "Get a token from https://test.pypi.org/manage/account/token/"; \
echo "Then set: export UV_PUBLISH_TOKEN=\"pypi-your-test-token\""; \
exit 1; \
fi
@cd installer && uv publish --index-url https://test.pypi.org/legacy/
@echo "✅ Published to TestPyPI!"
# Manual VM Testing - Start fresh VMs and show SSH command
vm-ubuntu:
@echo "Starting fresh Ubuntu VM..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@echo "Cleaning up any existing manual-ubuntu VM..."
@tart delete manual-ubuntu 2>/dev/null || true
@echo "Creating fresh Ubuntu VM..."
@tart clone ghcr.io/cirruslabs/ubuntu:latest manual-ubuntu && \
tart run --no-graphics manual-ubuntu >/dev/null 2>&1 & \
echo "Waiting for VM to start..." && \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-ubuntu)" && \
echo "" && \
echo " Username: admin" && \
echo " Password: admin" && \
echo "" && \
echo "To stop the VM: tart stop manual-ubuntu" && \
echo "To delete the VM: tart delete manual-ubuntu"
vm-fedora:
@echo "Starting fresh Fedora VM..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@echo "Cleaning up any existing manual-fedora VM..."
@tart delete manual-fedora 2>/dev/null || true
@echo "Creating fresh Fedora VM..."
@tart clone ghcr.io/cirruslabs/fedora:latest manual-fedora && \
tart run --no-graphics manual-fedora >/dev/null 2>&1 & \
echo "Waiting for VM to start..." && \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-fedora)" && \
echo "" && \
echo " Username: admin" && \
echo " Password: admin" && \
echo "" && \
echo "To stop the VM: tart stop manual-fedora" && \
echo "To delete the VM: tart delete manual-fedora"
vm-macos:
@echo "Starting fresh macOS VM..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@echo "Cleaning up any existing manual-macos VM..."
@tart delete manual-macos 2>/dev/null || true
@echo "Creating fresh macOS VM..."
@tart clone ghcr.io/cirruslabs/macos-tahoe-base:latest manual-macos && \
tart run --no-graphics manual-macos >/dev/null 2>&1 & \
echo "Waiting for VM to start..." && \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-macos)" && \
echo "" && \
echo " Username: admin" && \
echo " Password: admin" && \
echo "" && \
echo "To stop the VM: tart stop manual-macos" && \
echo "To delete the VM: tart delete manual-macos"
# Quick VM shell access (reuses existing VMs for faster startup)
vm-ubuntu-quick:
@echo "Starting Ubuntu VM (quick mode - reuses existing VM)..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
exit 1; \
fi
@if ! tart list | grep -q "manual-ubuntu"; then \
echo "Creating VM: manual-ubuntu"; \
tart clone ghcr.io/cirruslabs/ubuntu:latest manual-ubuntu; \
else \
echo "Using existing manual-ubuntu VM"; \
fi
@tart run --no-graphics manual-ubuntu >/dev/null 2>&1 & \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-ubuntu)" && \
echo "" && \
echo " Username: admin, Password: admin"
vm-fedora-quick:
@echo "Starting Fedora VM (quick mode - reuses existing VM)..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
exit 1; \
fi
@if ! tart list | grep -q "manual-fedora"; then \
echo "Creating VM: manual-fedora"; \
tart clone ghcr.io/cirruslabs/fedora:latest manual-fedora; \
else \
echo "Using existing manual-fedora VM"; \
fi
@tart run --no-graphics manual-fedora >/dev/null 2>&1 & \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-fedora)" && \
echo "" && \
echo " Username: admin, Password: admin"
vm-macos-quick:
@echo "Starting macOS VM (quick mode - reuses existing VM)..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
exit 1; \
fi
@if ! tart list | grep -q "manual-macos"; then \
echo "Creating VM: manual-macos"; \
tart clone ghcr.io/cirruslabs/macos-tahoe-base:latest manual-macos; \
else \
echo "Using existing manual-macos VM"; \
fi
@tart run --no-graphics manual-macos >/dev/null 2>&1 & \
sleep 5 && \
echo "" && \
echo "✅ VM started! To connect:" && \
echo "" && \
echo " ssh admin@$$(tart ip manual-macos)" && \
echo "" && \
echo " Username: admin, Password: admin"
# Clean up manual VMs
vm-clean:
@echo "Cleaning up manual VMs..."
@tart delete manual-ubuntu 2>/dev/null || echo " manual-ubuntu not found"
@tart delete manual-fedora 2>/dev/null || echo " manual-fedora not found"
@tart delete manual-macos 2>/dev/null || echo " manual-macos not found"
@echo "✅ Manual VMs cleaned up"
# List all Tart VMs
vm-list:
@echo "Available Tart VMs:"
@tart list
# Test installer from PyPI - default target tests all platforms
test-installer-pypi: test-installer-pypi-all
# Test installer from PyPI on Ubuntu (fresh clone)
test-installer-pypi-ubuntu:
@echo "Testing latest voice-mode-install from PyPI on fresh Ubuntu clone..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@uv run python scripts/test_installer.py ubuntu --pypi --backend tart --clone-fresh
# Test installer from PyPI on Fedora (fresh clone)
test-installer-pypi-fedora:
@echo "Testing latest voice-mode-install from PyPI on fresh Fedora clone..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@uv run python scripts/test_installer.py fedora --pypi --backend tart --clone-fresh
# Test installer from PyPI on all platforms (fresh clones)
test-installer-pypi-all:
@echo "Testing latest voice-mode-install from PyPI on fresh clones of all platforms..."
@if ! command -v tart >/dev/null 2>&1; then \
echo "❌ Tart is not installed!"; \
echo "Install from: https://github.com/cirruslabs/tart"; \
exit 1; \
fi
@echo ""
@echo "=== Testing Ubuntu (fresh clone) ==="; \
uv run python scripts/test_installer.py ubuntu --pypi --backend tart --clone-fresh || true; \
echo ""; \
echo "=== Testing Fedora (fresh clone) ==="; \
uv run python scripts/test_installer.py fedora --pypi --backend tart --clone-fresh || true