wasm-cli 0.14.2__tar.gz → 0.14.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wasm_cli-0.14.2/src/wasm_cli.egg-info → wasm_cli-0.14.4}/PKG-INFO +1 -1
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/pyproject.toml +1 -1
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/setup.py +1 -1
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/__init__.py +1 -1
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/webapp.py +76 -6
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/update_checker.py +21 -16
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/monorepo.py +33 -19
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/service_manager.py +7 -7
- {wasm_cli-0.14.2 → wasm_cli-0.14.4/src/wasm_cli.egg-info}/PKG-INFO +1 -1
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/LICENSE +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/MANIFEST.in +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/README.md +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/docs/MONITOR.md +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/docs/OBS_SETUP.md +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/docs/assets/logo.png +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/docs/assets/logo_bg.png +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/man/wasm.1 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/setup.cfg +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/__main__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/backup.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/cert.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/config.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/db.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/health.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/monitor.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/service.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/setup.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/site.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/store.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/version.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/commands/web.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/interactive.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/cli/parser.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/completions/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/completions/_wasm +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/completions/wasm.bash +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/completions/wasm.fish +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/config.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/dependencies.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/exceptions.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/logger.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/store.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/core/utils.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/base.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/package_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/path_resolver.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/prisma.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/turbo.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/helpers/workspace.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/nextjs.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/nodejs.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/python.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/registry.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/static.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/deployers/vite.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/main.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/apache_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/backup_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/base_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/cert_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/base.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/mongodb.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/mysql.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/postgres.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/redis.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/database/registry.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/nginx_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/managers/source_manager.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/monitor/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/monitor/ai_analyzer.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/monitor/email_notifier.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/monitor/process_monitor.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/monitor/threat_store.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/apache/proxy.conf.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/apache/static.conf.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/nginx/monorepo.conf.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/nginx/proxy.conf.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/nginx/static.conf.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/templates/systemd/app.service.j2 +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/validators/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/validators/domain.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/validators/port.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/validators/source.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/validators/ssh.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/apps.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/auth.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/backups.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/certs.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/config.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/databases.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/jobs.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/monitor.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/router.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/services.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/sites.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/api/system.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/auth.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/jobs.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/server.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/css/main.css +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/index.html +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/components/cards.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/components/jobs.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/components/metrics.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/components/skeleton.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/api.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/dialogs.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/notifications.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/router.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/search.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/shortcuts.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/theme.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/ui.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/core/websocket.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/main.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/apps.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/backups.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/certs.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/config.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/dashboard.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/databases.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/jobs.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/logs.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/monitor.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/services.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/js/pages/sites.js +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/login.html +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/logo.png +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/static/logo.webp +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/websockets/__init__.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm/web/websockets/router.py +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm_cli.egg-info/SOURCES.txt +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm_cli.egg-info/dependency_links.txt +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm_cli.egg-info/entry_points.txt +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm_cli.egg-info/requires.txt +0 -0
- {wasm_cli-0.14.2 → wasm_cli-0.14.4}/src/wasm_cli.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wasm-cli"
|
|
7
|
-
version = "0.14.
|
|
7
|
+
version = "0.14.4"
|
|
8
8
|
description = "Web App System Management - Deploy and manage web applications on Linux servers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "WASM-NCSAL" }
|
|
@@ -9,7 +9,7 @@ from setuptools import setup, find_packages
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="wasm-cli",
|
|
12
|
-
version="0.14.
|
|
12
|
+
version="0.14.4",
|
|
13
13
|
description="Web App System Management - Deploy and manage web applications on Linux servers",
|
|
14
14
|
author="Yago López Prado",
|
|
15
15
|
author_email="yago.lopez.adeje@gmail.com",
|
|
@@ -594,22 +594,28 @@ def _handle_update(args: Namespace) -> int:
|
|
|
594
594
|
else:
|
|
595
595
|
logger.substep(f"Detected: {app_type}")
|
|
596
596
|
|
|
597
|
+
# Handle monorepo updates with dedicated flow
|
|
598
|
+
if app_type == "monorepo":
|
|
599
|
+
return _handle_monorepo_update(
|
|
600
|
+
args, app_path, app_name, domain, logger, total_steps
|
|
601
|
+
)
|
|
602
|
+
|
|
597
603
|
deployer = get_deployer(app_type, verbose=args.verbose)
|
|
598
604
|
deployer.app_path = app_path
|
|
599
605
|
deployer.app_name = app_name
|
|
600
606
|
deployer.domain = domain
|
|
601
607
|
deployer._package_manager = package_manager
|
|
602
|
-
|
|
608
|
+
|
|
603
609
|
# Run pre_install to detect package manager and prisma
|
|
604
610
|
deployer.pre_install()
|
|
605
611
|
logger.substep(f"Package manager: {deployer.package_manager}")
|
|
606
612
|
if deployer.has_prisma:
|
|
607
613
|
logger.substep("Prisma detected")
|
|
608
|
-
|
|
614
|
+
|
|
609
615
|
# Step 4: Install dependencies (without stopping the app)
|
|
610
616
|
logger.step(4, total_steps, "Installing dependencies")
|
|
611
617
|
deployer.install_dependencies()
|
|
612
|
-
|
|
618
|
+
|
|
613
619
|
# Step 5: Generate Prisma and run migrations if needed
|
|
614
620
|
if deployer.has_prisma:
|
|
615
621
|
logger.step(5, total_steps, "Updating Prisma")
|
|
@@ -617,11 +623,11 @@ def _handle_update(args: Namespace) -> int:
|
|
|
617
623
|
deployer.run_prisma_migrate(deploy=True)
|
|
618
624
|
else:
|
|
619
625
|
logger.step(5, total_steps, "Prisma not detected, skipping")
|
|
620
|
-
|
|
626
|
+
|
|
621
627
|
# Step 6: Build application (without stopping the app)
|
|
622
628
|
logger.step(6, total_steps, "Building application")
|
|
623
629
|
deployer.build()
|
|
624
|
-
|
|
630
|
+
|
|
625
631
|
# Step 7: Restart service (only if not static)
|
|
626
632
|
logger.step(7, total_steps, "Restarting application")
|
|
627
633
|
service_manager = ServiceManager(verbose=args.verbose)
|
|
@@ -660,7 +666,71 @@ def _handle_update(args: Namespace) -> int:
|
|
|
660
666
|
else:
|
|
661
667
|
logger.warning("Application restarted but may not be running correctly")
|
|
662
668
|
logger.info(f"Check logs with: wasm logs {domain}")
|
|
663
|
-
|
|
669
|
+
|
|
670
|
+
return 0
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
def _handle_monorepo_update(args, app_path, app_name, domain, logger, total_steps):
|
|
674
|
+
"""Handle update for monorepo applications."""
|
|
675
|
+
from wasm.deployers.monorepo import MonorepoDeployer
|
|
676
|
+
|
|
677
|
+
deployer = MonorepoDeployer(verbose=args.verbose)
|
|
678
|
+
deployer.app_path = app_path
|
|
679
|
+
deployer.app_name = app_name
|
|
680
|
+
deployer.domain = domain
|
|
681
|
+
deployer.package_manager = "pnpm"
|
|
682
|
+
|
|
683
|
+
# Step 4: Install dependencies
|
|
684
|
+
logger.step(4, total_steps, "Installing dependencies")
|
|
685
|
+
deployer._install_dependencies()
|
|
686
|
+
|
|
687
|
+
# Step 5: Run Prisma migrations
|
|
688
|
+
logger.step(5, total_steps, "Running database migrations")
|
|
689
|
+
deployer._run_prisma_migrations()
|
|
690
|
+
|
|
691
|
+
# Step 6: Build all workspaces
|
|
692
|
+
logger.step(6, total_steps, "Building applications")
|
|
693
|
+
deployer._set_permissions()
|
|
694
|
+
deployer._build_all()
|
|
695
|
+
|
|
696
|
+
# Step 7: Restart all workspace services
|
|
697
|
+
logger.step(7, total_steps, "Restarting applications")
|
|
698
|
+
service_manager = ServiceManager(verbose=args.verbose)
|
|
699
|
+
|
|
700
|
+
# Find all services for this monorepo
|
|
701
|
+
from wasm.core.store import get_store
|
|
702
|
+
store = get_store()
|
|
703
|
+
app = store.get_app(domain)
|
|
704
|
+
|
|
705
|
+
restarted = []
|
|
706
|
+
if app:
|
|
707
|
+
all_services = store.list_services()
|
|
708
|
+
services = [s for s in all_services if s.app_id == app.id]
|
|
709
|
+
for service in services:
|
|
710
|
+
logger.substep(f"Restarting {service.name}")
|
|
711
|
+
try:
|
|
712
|
+
service_manager.restart(service.name)
|
|
713
|
+
restarted.append(service.name)
|
|
714
|
+
except Exception as e:
|
|
715
|
+
logger.warning(f"Failed to restart {service.name}: {e}")
|
|
716
|
+
else:
|
|
717
|
+
# Fallback: restart by app_name pattern
|
|
718
|
+
status = service_manager.get_status(app_name)
|
|
719
|
+
if status.get("exists"):
|
|
720
|
+
service_manager.restart(app_name)
|
|
721
|
+
restarted.append(app_name)
|
|
722
|
+
|
|
723
|
+
if restarted:
|
|
724
|
+
import time
|
|
725
|
+
time.sleep(3)
|
|
726
|
+
logger.success(f"Monorepo updated successfully: {domain}")
|
|
727
|
+
logger.blank()
|
|
728
|
+
for name in restarted:
|
|
729
|
+
logger.key_value("Restarted", name)
|
|
730
|
+
else:
|
|
731
|
+
logger.warning("No services found to restart")
|
|
732
|
+
logger.info(f"Try redeploying: wasm create -d {domain}")
|
|
733
|
+
|
|
664
734
|
return 0
|
|
665
735
|
|
|
666
736
|
|
|
@@ -45,7 +45,10 @@ class UpdateChecker:
|
|
|
45
45
|
if cls._is_cache_valid():
|
|
46
46
|
cached_data = cls._read_cache()
|
|
47
47
|
if cached_data and cached_data.get("has_update"):
|
|
48
|
-
|
|
48
|
+
cached_version = cached_data["latest_version"]
|
|
49
|
+
# Re-verify against current version (user may have updated)
|
|
50
|
+
if cls._is_newer_version(cached_version, __version__):
|
|
51
|
+
cls._update_version = cached_version
|
|
49
52
|
return
|
|
50
53
|
|
|
51
54
|
# Start background thread for network request
|
|
@@ -270,28 +273,17 @@ class UpdateChecker:
|
|
|
270
273
|
if pipx_path.exists():
|
|
271
274
|
return "pipx"
|
|
272
275
|
|
|
273
|
-
# Check
|
|
274
|
-
|
|
275
|
-
[sys.executable, "-m", "pip", "show", "wasm-cli"],
|
|
276
|
-
capture_output=True,
|
|
277
|
-
text=True,
|
|
278
|
-
timeout=2
|
|
279
|
-
)
|
|
280
|
-
if result.returncode == 0:
|
|
281
|
-
# Check if installed in editable mode (from source)
|
|
282
|
-
if "Editable project location:" in result.stdout or "-e " in result.stdout:
|
|
283
|
-
return "source"
|
|
284
|
-
return "pip"
|
|
276
|
+
# Check system package managers BEFORE pip, since system packages
|
|
277
|
+
# install Python files that pip can also detect (false positive)
|
|
285
278
|
|
|
286
|
-
# Check system package managers
|
|
287
279
|
# APT (Ubuntu, Debian) - package is called "wasm" not "wasm-cli"
|
|
288
280
|
if Path("/var/lib/dpkg/status").exists():
|
|
289
281
|
result = subprocess.run(
|
|
290
|
-
["dpkg", "-
|
|
282
|
+
["dpkg", "-s", "wasm"],
|
|
291
283
|
capture_output=True,
|
|
292
284
|
timeout=2
|
|
293
285
|
)
|
|
294
|
-
if result.returncode == 0
|
|
286
|
+
if result.returncode == 0:
|
|
295
287
|
return "apt"
|
|
296
288
|
|
|
297
289
|
# DNF/YUM (Fedora, RHEL, CentOS)
|
|
@@ -319,6 +311,19 @@ class UpdateChecker:
|
|
|
319
311
|
except FileNotFoundError:
|
|
320
312
|
pass
|
|
321
313
|
|
|
314
|
+
# Check pip (after system package managers)
|
|
315
|
+
result = subprocess.run(
|
|
316
|
+
[sys.executable, "-m", "pip", "show", "wasm-cli"],
|
|
317
|
+
capture_output=True,
|
|
318
|
+
text=True,
|
|
319
|
+
timeout=2
|
|
320
|
+
)
|
|
321
|
+
if result.returncode == 0:
|
|
322
|
+
# Check if installed in editable mode (from source)
|
|
323
|
+
if "Editable project location:" in result.stdout or "-e " in result.stdout:
|
|
324
|
+
return "source"
|
|
325
|
+
return "pip"
|
|
326
|
+
|
|
322
327
|
except Exception as e:
|
|
323
328
|
logger.debug(f"Failed to detect installation method: {e}")
|
|
324
329
|
|
|
@@ -187,32 +187,46 @@ class MonorepoDeployer:
|
|
|
187
187
|
"""
|
|
188
188
|
Detect if path contains a Turborepo/pnpm monorepo.
|
|
189
189
|
|
|
190
|
+
Requires turbo.json AND workspace configuration AND at least 2
|
|
191
|
+
deployable applications in apps/ to distinguish from single apps
|
|
192
|
+
that use Turborepo for build caching.
|
|
193
|
+
|
|
190
194
|
Args:
|
|
191
195
|
path: Path to check.
|
|
192
196
|
|
|
193
197
|
Returns:
|
|
194
198
|
True if this deployer can handle the project.
|
|
195
199
|
"""
|
|
196
|
-
#
|
|
197
|
-
if (path / "turbo.json").exists():
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
#
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
200
|
+
# Must have turbo.json (primary monorepo build tool)
|
|
201
|
+
if not (path / "turbo.json").exists():
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
# Must have workspace configuration
|
|
205
|
+
has_workspace_config = (path / "pnpm-workspace.yaml").exists()
|
|
206
|
+
if not has_workspace_config:
|
|
207
|
+
package_json = path / "package.json"
|
|
208
|
+
if package_json.exists():
|
|
209
|
+
try:
|
|
210
|
+
with open(package_json) as f:
|
|
211
|
+
pkg = json.load(f)
|
|
212
|
+
has_workspace_config = "workspaces" in pkg
|
|
213
|
+
except (json.JSONDecodeError, OSError):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
if not has_workspace_config:
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
# Must have multiple deployable apps in apps/ directory
|
|
220
|
+
apps_dir = path / "apps"
|
|
221
|
+
if not apps_dir.is_dir():
|
|
222
|
+
return False
|
|
223
|
+
|
|
224
|
+
app_count = sum(
|
|
225
|
+
1 for d in apps_dir.iterdir()
|
|
226
|
+
if d.is_dir() and (d / "package.json").exists()
|
|
227
|
+
)
|
|
214
228
|
|
|
215
|
-
return
|
|
229
|
+
return app_count >= 2
|
|
216
230
|
|
|
217
231
|
def _run(
|
|
218
232
|
self,
|
|
@@ -140,15 +140,15 @@ class ServiceManager(BaseManager):
|
|
|
140
140
|
|
|
141
141
|
def service_exists(self, name: str) -> bool:
|
|
142
142
|
"""
|
|
143
|
-
Check if a service exists.
|
|
144
|
-
|
|
143
|
+
Check if a service exists (new or legacy format).
|
|
144
|
+
|
|
145
145
|
Args:
|
|
146
146
|
name: Service name.
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
Returns:
|
|
149
149
|
True if service exists.
|
|
150
150
|
"""
|
|
151
|
-
service_file = self.
|
|
151
|
+
service_file = self._resolve_service_file(name)
|
|
152
152
|
return service_file.exists()
|
|
153
153
|
|
|
154
154
|
def list_services(self, all_services: bool = False) -> List[Dict]:
|
|
@@ -507,12 +507,12 @@ class ServiceManager(BaseManager):
|
|
|
507
507
|
def get_service_config(self, name: str) -> Optional[str]:
|
|
508
508
|
"""
|
|
509
509
|
Get service configuration content.
|
|
510
|
-
|
|
510
|
+
|
|
511
511
|
Args:
|
|
512
512
|
name: Service name.
|
|
513
|
-
|
|
513
|
+
|
|
514
514
|
Returns:
|
|
515
515
|
Service file content or None.
|
|
516
516
|
"""
|
|
517
|
-
service_file = self.
|
|
517
|
+
service_file = self._resolve_service_file(name)
|
|
518
518
|
return read_file(service_file, sudo=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|