xcorecli 1.1.0__tar.gz → 2.0.0__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.
Files changed (74) hide show
  1. {xcorecli-1.1.0 → xcorecli-2.0.0}/PKG-INFO +2 -2
  2. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/index.md +7 -2
  3. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/reference.md +5 -26
  4. {xcorecli-1.1.0 → xcorecli-2.0.0}/mkdocs.yml +0 -2
  5. {xcorecli-1.1.0 → xcorecli-2.0.0}/pyproject.toml +2 -2
  6. {xcorecli-1.1.0 → xcorecli-2.0.0}/uv.lock +1 -1
  7. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/main.py +0 -2
  8. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/manager/cli.py +74 -0
  9. xcorecli-1.1.0/docs/deploy/index.md +0 -406
  10. xcorecli-1.1.0/xcli/deploy/cli.py +0 -538
  11. xcorecli-1.1.0/xcli/deploy/config.py +0 -289
  12. xcorecli-1.1.0/xcli/deploy/generate.py +0 -122
  13. xcorecli-1.1.0/xcli/deploy/runner.py +0 -692
  14. xcorecli-1.1.0/xcli/worker/__init__.py +0 -0
  15. {xcorecli-1.1.0 → xcorecli-2.0.0}/.github/workflows/publish.yml +0 -0
  16. {xcorecli-1.1.0 → xcorecli-2.0.0}/.gitignore +0 -0
  17. {xcorecli-1.1.0 → xcorecli-2.0.0}/.python-version +0 -0
  18. {xcorecli-1.1.0 → xcorecli-2.0.0}/.vscode/configurationCache.log +0 -0
  19. {xcorecli-1.1.0 → xcorecli-2.0.0}/.vscode/dryrun.log +0 -0
  20. {xcorecli-1.1.0 → xcorecli-2.0.0}/.vscode/settings.json +0 -0
  21. {xcorecli-1.1.0 → xcorecli-2.0.0}/.vscode/targets.log +0 -0
  22. {xcorecli-1.1.0 → xcorecli-2.0.0}/README.md +0 -0
  23. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/commands/health.md +0 -0
  24. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/commands/init.md +0 -0
  25. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/config/index.md +0 -0
  26. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/getting-started/auth.md +0 -0
  27. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/getting-started/configuration.md +0 -0
  28. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/getting-started/install.md +0 -0
  29. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/manager/index.md +0 -0
  30. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/manager/monitoring.md +0 -0
  31. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/manager/services.md +0 -0
  32. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/migration/index.md +0 -0
  33. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/index.md +0 -0
  34. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/install.md +0 -0
  35. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/local.md +0 -0
  36. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/marketplace.md +0 -0
  37. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/runtime.md +0 -0
  38. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/security.md +0 -0
  39. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/plugin/update.md +0 -0
  40. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/sandbox/index.md +0 -0
  41. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/worker/index.md +0 -0
  42. {xcorecli-1.1.0 → xcorecli-2.0.0}/docs/worker/process.md +0 -0
  43. {xcorecli-1.1.0 → xcorecli-2.0.0}/makefile +0 -0
  44. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/__init__.py +0 -0
  45. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/_credentials.py +0 -0
  46. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/_run.py +0 -0
  47. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/_xcore.py +0 -0
  48. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/config/__init__.py +0 -0
  49. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/config/cli.py +0 -0
  50. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/config/runtime.py +0 -0
  51. {xcorecli-1.1.0/xcli/deploy → xcorecli-2.0.0/xcli/init}/__init__.py +0 -0
  52. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/init/manager.py +0 -0
  53. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/init/upgrade.py +0 -0
  54. {xcorecli-1.1.0/xcli/init → xcorecli-2.0.0/xcli/manager}/__init__.py +0 -0
  55. {xcorecli-1.1.0/xcli/manager → xcorecli-2.0.0/xcli/marketplace}/__init__.py +0 -0
  56. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/marketplace/cli.py +0 -0
  57. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/migrations/__init__.py +0 -0
  58. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/migrations/cli.py +0 -0
  59. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/migrations/runtime.py +0 -0
  60. {xcorecli-1.1.0/xcli/marketplace → xcorecli-2.0.0/xcli/plugin}/__init__.py +0 -0
  61. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/cli.py +0 -0
  62. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/install_commands.py +0 -0
  63. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/local_commands.py +0 -0
  64. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/marketplace_commands.py +0 -0
  65. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/runtime_commands.py +0 -0
  66. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/scaffold.py +0 -0
  67. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/security_commands.py +0 -0
  68. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/shared.py +0 -0
  69. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/plugin/update_commands.py +0 -0
  70. {xcorecli-1.1.0/xcli/plugin → xcorecli-2.0.0/xcli/sandbox}/__init__.py +0 -0
  71. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/sandbox/cli.py +0 -0
  72. {xcorecli-1.1.0/xcli/sandbox → xcorecli-2.0.0/xcli/worker}/__init__.py +0 -0
  73. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/worker/cli.py +0 -0
  74. {xcorecli-1.1.0 → xcorecli-2.0.0}/xcli/worker/worker.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: xcorecli
3
- Version: 1.1.0
4
- Summary: CLI for xcore — configuration, plugins, deployment
3
+ Version: 2.0.0
4
+ Summary: CLI for xcore — configuration, plugins, monitoring
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: alembic>=1.18.0
7
7
  Requires-Dist: httpx>=0.27
@@ -9,7 +9,6 @@
9
9
 
10
10
  - **Project Initialization**: Seamlessly scaffold new projects and manage `integration.yaml`.
11
11
  - **Plugin Lifecycle**: Full control over installing, signing, and updating plugins.
12
- - **Production Deploy**: Deploy plugins to remote servers via SSH with pre/post hooks.
13
12
  - **Real-time Monitoring**: Integrated dashboard for service health and resource usage.
14
13
  - **Worker Orchestration**: Manage Celery/XWorker processes with ease.
15
14
  - **Security & Sandboxing**: Resource isolation and AST-based whitelisting for plugins.
@@ -30,5 +29,11 @@ make install
30
29
 
31
30
  - [Installation Guide](getting-started/install.md)
32
31
  - [Authentication Setup](getting-started/auth.md)
33
- - [Deploy to Production](deploy/index.md)
34
32
  - [Core Commands Reference](reference.md)
33
+
34
+ !!! info "Production deployment"
35
+ Deploying plugin bundles to remote servers is no longer part of
36
+ `xcorecli` — it's fully handled by the standalone
37
+ [`xcore-agent`](https://github.com/traoreera/xcore-agent) deployment
38
+ agent (Hub artifact fetch, signature verification, install/rollback,
39
+ systemd/Docker/Kubernetes supervisors, CI/CD watch loop).
@@ -21,32 +21,11 @@ A comprehensive list of all commands available in `xcorecli`.
21
21
  - `manager services reload`: Reconnect a service.
22
22
  - `manager services unload`: Shutdown a service.
23
23
 
24
- ## `deploy` Production Deployment
25
-
26
- - `deploy init`: Generate a `xcore-deploy.yaml` template file.
27
- - `deploy list`: Show targets, plugins, extensions, and hooks declared in the config.
28
- - `deploy <target>`: Deploy integration.yaml + extensions + plugins to a remote server.
29
- - `deploy status <target>`: Show plugin state on a remote server via the XCore API.
30
-
31
- **Key options for `deploy <target>`:**
32
-
33
- | Option | Description |
34
- |---|---|
35
- | `--plugin <name>` | Deploy only one plugin (skips extensions + integration) |
36
- | `--dry-run` | Simulate without sending anything |
37
- | `--no-reload` | Transfer files without triggering reload/restart |
38
- | `--file <path>` | Use an alternate config file |
39
-
40
- **Deploy order:** `integration.yaml` → extensions (services) → plugins
41
-
42
- **Sources:** each plugin/extension accepts `source: ./local/path` OR `repo: https://github.com/org/repo` (public), with optional `token: "${GITHUB_TOKEN}"` for private repos or `git@github.com:...` SSH URLs.
43
-
44
- **Hook levels:**
45
-
46
- | Level | Keys | When |
47
- |---|---|---|
48
- | Global | `hooks.pre_deploy` / `hooks.post_deploy` | Once per full deploy run |
49
- | Per-plugin/extension | `hooks.pre_deploy` / `post_deploy` | Before/after each item |
24
+ !!! info "Production deployment moved"
25
+ `deploy` (init/list/status, SSH transfer, pre/post hooks) is no
26
+ longer part of `xcorecli` — it's fully replaced by the standalone
27
+ [`xcore-agent`](https://github.com/traoreera/xcore-agent) deployment
28
+ agent.
50
29
 
51
30
  ---
52
31
 
@@ -67,8 +67,6 @@ nav:
67
67
  - Marketplace: plugin/marketplace.md
68
68
  - Security: plugin/security.md
69
69
  - Updates: plugin/update.md
70
- - Deploy:
71
- - Overview: deploy/index.md
72
70
  - Sandbox: sandbox/index.md
73
71
  - Worker:
74
72
  - Overview: worker/index.md
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "xcorecli"
7
- version = "1.1.0"
8
- description = "CLI for xcore — configuration, plugins, deployment"
7
+ version = "2.0.0"
8
+ description = "CLI for xcore — configuration, plugins, monitoring"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
11
11
  dependencies = [
@@ -773,7 +773,7 @@ wheels = [
773
773
 
774
774
  [[package]]
775
775
  name = "xcorecli"
776
- version = "1.1.0"
776
+ version = "2.0.0"
777
777
  source = { editable = "." }
778
778
  dependencies = [
779
779
  { name = "alembic" },
@@ -13,7 +13,6 @@ _console = Console()
13
13
  from xcli.init.manager import _DB_URLS, create_project
14
14
  from xcli.init.upgrade import run_upgrade as _run_upgrade
15
15
  from xcli.config.cli import app as config_app
16
- from xcli.deploy.cli import app as deploy_app
17
16
  from xcli.manager.cli import app as manager_app
18
17
  from xcli.migrations.cli import app as migrations_app
19
18
  from xcli.plugin.cli import app as plugin_app
@@ -150,7 +149,6 @@ def services() -> None:
150
149
  # ── sub-apps ──────────────────────────────────────────────────
151
150
 
152
151
  app.add_typer(config_app, name="config")
153
- app.add_typer(deploy_app, name="deploy")
154
152
  app.add_typer(plugin_app, name="plugin")
155
153
  app.add_typer(sandbox_app, name="sandbox")
156
154
  app.add_typer(worker_app, name="worker")
@@ -138,6 +138,57 @@ def _build_resources_table() -> Table:
138
138
  except (psutil.NoSuchProcess, psutil.AccessDenied):
139
139
  pass
140
140
 
141
+ # Plugins en mode "trusted"/"sandboxed(threaded)" tournent DANS le
142
+ # process API principal (pas de sous-process dédié) — donc pas de PID
143
+ # à eux. Plutôt que d'afficher des tirets, on retombe sur le process
144
+ # API (retrouvé via le PID file écrit par `xcli manager start`, ou à
145
+ # défaut par scan cmdline) et on l'affiche comme ressource *partagée*.
146
+ main_proc: psutil.Process | None = None
147
+ try:
148
+ from xcli.worker.worker import PID_API, _is_running, _read_pid
149
+
150
+ main_pid = _read_pid(PID_API)
151
+ if main_pid and _is_running(main_pid):
152
+ main_proc = psutil.Process(main_pid)
153
+ except Exception:
154
+ main_proc = None
155
+
156
+ if main_proc is None:
157
+ # Pas de PID file (démarrage en foreground sans --detach, ou
158
+ # process lancé hors xcli) — on cherche le process uvicorn qui
159
+ # sert l'app, en excluant les sandbox workers déjà identifiés.
160
+ sandboxed_pids = {p.pid for p in sandbox_pids.values()}
161
+ for proc in psutil.process_iter(["pid", "cmdline"]):
162
+ if proc.pid in sandboxed_pids:
163
+ continue
164
+ try:
165
+ cmd = proc.info["cmdline"] or []
166
+ if any("uvicorn" in str(c) for c in cmd):
167
+ main_proc = proc
168
+ break
169
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
170
+ pass
171
+
172
+ main_cpu_str = main_mem_str = main_conn_str = "—"
173
+ main_pid_str = "—"
174
+ if main_proc is not None:
175
+ try:
176
+ main_pid_str = str(main_proc.pid)
177
+ cpu = main_proc.cpu_percent(interval=0.05)
178
+ cpu_color = "red" if cpu > 80 else ("yellow" if cpu > 40 else "green")
179
+ main_cpu_str = f"[{cpu_color}]{cpu:.1f}[/{cpu_color}]"
180
+
181
+ mem = main_proc.memory_info().rss / 1024**2
182
+ mem_color = "red" if mem > 400 else ("yellow" if mem > 200 else "magenta")
183
+ main_mem_str = f"[{mem_color}]{mem:.1f}[/{mem_color}]"
184
+
185
+ try:
186
+ main_conn_str = str(len(main_proc.net_connections()))
187
+ except (psutil.AccessDenied, AttributeError):
188
+ main_conn_str = "?"
189
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
190
+ main_proc = None
191
+
141
192
  table = Table(title=f"Plugin Resources [dim]{plugins_root}[/dim]", show_lines=True)
142
193
  table.add_column("Plugin", style="cyan", no_wrap=True)
143
194
  table.add_column("Mode", justify="center")
@@ -196,9 +247,25 @@ def _build_resources_table() -> Table:
196
247
  state_str = "[green]running[/green]" if state == "running" else f"[yellow]{state}[/yellow]"
197
248
  except (psutil.NoSuchProcess, psutil.AccessDenied):
198
249
  state_str = "[red]gone[/red]"
250
+ elif main_proc is not None:
251
+ # Plugin en process partagé (trusted / non-sandboxé) : on
252
+ # affiche les métriques du process API, avec un marqueur "~"
253
+ # pour signaler que c'est une valeur partagée entre plugins,
254
+ # pas exclusive à celui-ci.
255
+ pid_str = f"~{main_pid_str}"
256
+ cpu_str = main_cpu_str
257
+ mem_str = main_mem_str
258
+ conn_str = main_conn_str
259
+ state_str = "[cyan]in-process[/cyan] [dim](partagé)[/dim]"
199
260
 
200
261
  table.add_row(name, mode, pid_str, cpu_str, mem_str, disk_str, conn_str, state_str)
201
262
 
263
+ if main_proc is not None and any(name not in sandbox_pids for name in plugin_names):
264
+ table.caption = (
265
+ "[dim]~PID = process API partagé entre plugins \"in-process (partagé)\" — "
266
+ "CPU/Mem/Net Conn reflètent le process entier, pas ce plugin seul.[/dim]"
267
+ )
268
+
202
269
  return table
203
270
 
204
271
 
@@ -595,12 +662,19 @@ def start(
595
662
 
596
663
  console.print(f"[dim]→ uvicorn {app_path} --host {resolved_host} --port {resolved_port}[/dim]")
597
664
  console.print("[dim]Ctrl+C to stop[/dim]\n")
665
+ PID_DIR.mkdir(parents=True, exist_ok=True)
598
666
  try:
599
667
  proc = subprocess.Popen(cmd)
668
+ # Écrit le PID même en foreground : `xcli manager resources`/`top`
669
+ # dans un autre terminal en a besoin pour retrouver le process API
670
+ # (plugins "trusted" partagent ce process, pas de PID dédié).
671
+ _write_pid(PID_API, proc.pid)
600
672
  proc.wait()
601
673
  except KeyboardInterrupt:
602
674
  proc.terminate()
603
675
  proc.wait()
676
+ finally:
677
+ PID_API.unlink(missing_ok=True)
604
678
 
605
679
 
606
680
  @app.command("stop")
@@ -1,406 +0,0 @@
1
- # Deploy — Déploiement en production
2
-
3
- Le module `deploy` permet de déployer des plugins, extensions (services), fichiers de configuration (.env, certificats…) et le fichier `integration.yaml` vers des serveurs distants via SSH/SFTP. Il supporte les sources **locales** et les **repos GitHub** (publics et privés), avec un système de hooks pre/post.
4
-
5
- ## Quickstart
6
-
7
- ```bash
8
- # 1. Scan automatique du projet (détecte plugins, extensions, integration.yaml)
9
- xcli deploy generate
10
-
11
- # 2. Éditer xcore-deploy.yaml (targets, tweaks)
12
-
13
- # 3. Simuler sans rien envoyer
14
- xcli deploy run production --dry-run
15
-
16
- # 4. Déployer
17
- xcli deploy run production
18
- ```
19
-
20
- ---
21
-
22
- ## Structure complète de `xcore-deploy.yaml`
23
-
24
- ```yaml
25
- version: "1"
26
-
27
- # ── Serveurs ─────────────────────────────────────────────────────────────────
28
- targets:
29
- production:
30
- host: prod.monapp.com
31
- port: 22
32
- user: deploy
33
- ssh_key: ~/.ssh/id_ed25519
34
- xcore_url: https://api.monapp.com
35
- xcore_token: "${XCORE_ADMIN_TOKEN}"
36
- plugins_root: /opt/xcore/app/plugins
37
- extensions_root: /opt/xcore/app/extensions
38
-
39
- staging:
40
- host: staging.monapp.com
41
- user: deploy
42
- ssh_key: ~/.ssh/id_ed25519
43
- xcore_url: https://staging.monapp.com
44
- xcore_token: "${XCORE_STAGING_TOKEN}"
45
- plugins_root: /opt/xcore/app/plugins
46
-
47
- # ── Hooks globaux ─────────────────────────────────────────────────────────────
48
- hooks:
49
- pre_deploy:
50
- - cmd: "uv run xcli plugin security validate --save"
51
- - cmd: "uv run pytest tests/ -x -q"
52
- ignore_errors: false
53
-
54
- post_deploy:
55
- - cmd: "uv run xcli deploy status production"
56
- ignore_errors: true
57
-
58
- # ── Config XCore (integration.yaml) ──────────────────────────────────────────
59
- integration:
60
- source: ./integration.yaml
61
- remote_path: /opt/xcore/integration.yaml
62
- restart_xcore: true
63
-
64
- # ── Fichiers (config, .env, certificats) ──────────────────────────────────────
65
- # Copiés vers le serveur avant les extensions et plugins.
66
- files:
67
- - source: ./.env
68
- dest: /opt/xcore/.env
69
- # only: [production]
70
-
71
- - source: ./conf/private.pem
72
- dest: /opt/xcore/conf/private.pem
73
- only: [production]
74
-
75
- - source: ./conf/public.pem
76
- dest: /opt/xcore/conf/public.pem
77
-
78
- # ── Extensions (services) ─────────────────────────────────────────────────────
79
- extensions:
80
- - name: mail
81
- source: ./extensions/mail
82
- restart: true
83
- only: [production]
84
-
85
- - name: pubsub
86
- repo: https://github.com/org/xcore-pubsub
87
- ref: v1.0.0
88
- restart: true
89
-
90
- # ── Plugins ───────────────────────────────────────────────────────────────────
91
- plugins:
92
- - name: auth
93
- source: ./app/auth
94
- sign: true
95
- reload: true
96
-
97
- - name: billing
98
- repo: https://github.com/org/billing-plugin
99
- ref: main
100
- sign: true
101
- reload: true
102
-
103
- - name: pdf-generator
104
- source: ./app/pdf-generator
105
- reload: true
106
- only: [production]
107
- hooks:
108
- pre_deploy:
109
- - cmd: "uv run xcli plugin security validate ./app/pdf-generator"
110
- post_deploy:
111
- - cmd: "echo 'pdf-generator déployé'"
112
- ignore_errors: true
113
- ```
114
-
115
- ---
116
-
117
- ## Section `files:` — Copie de fichiers
118
-
119
- Les fichiers déclarés dans `files:` sont copiés vers le serveur **avant** les extensions et plugins. Utile pour `.env`, certificats, fichiers de config, etc.
120
-
121
- ```yaml
122
- files:
123
- - source: ./.env
124
- dest: /opt/xcore/.env
125
- - source: ./conf/private.pem
126
- dest: /opt/xcore/conf/private.pem
127
- only: [production]
128
- - source: ./config/prod.yaml
129
- dest: /opt/xcore/config/prod.yaml
130
- ```
131
-
132
- | Champ | Description |
133
- |---|---|
134
- | `source` | Chemin local du fichier (relatif à la racine du projet) |
135
- | `dest` | Chemin distant de destination |
136
- | `only` | (optionnel) Restreindre à certains targets |
137
-
138
- ---
139
-
140
- ## Sources : local vs GitHub
141
-
142
- Chaque plugin et extension accepte soit `source:` (chemin local), soit `repo:` (dépôt Git).
143
-
144
- ### Source locale
145
-
146
- ```yaml
147
- plugins:
148
- - name: mon-plugin
149
- source: ./app/mon-plugin
150
- ```
151
-
152
- ### GitHub — repo public
153
-
154
- ```yaml
155
- plugins:
156
- - name: mon-plugin
157
- repo: https://github.com/org/mon-plugin
158
- ref: v2.1.0
159
- ```
160
-
161
- ### GitHub — repo privé via token
162
-
163
- ```yaml
164
- plugins:
165
- - name: mon-plugin
166
- repo: https://github.com/org/mon-plugin-prive
167
- ref: main
168
- token: "${GITHUB_TOKEN}"
169
- ```
170
-
171
- ### GitHub — repo privé via SSH
172
-
173
- ```yaml
174
- plugins:
175
- - name: mon-plugin
176
- repo: git@github.com:org/mon-plugin-prive.git
177
- ref: main
178
- # utilise ssh_key du target
179
- ```
180
-
181
- ### Plugin dans un sous-dossier du repo
182
-
183
- ```yaml
184
- plugins:
185
- - name: mon-plugin
186
- repo: https://github.com/org/monorepo
187
- ref: main
188
- subdirectory: packages/mon-plugin
189
- ```
190
-
191
- !!! note "Clone automatique"
192
- xcli fait un `git clone --depth 1 --branch <ref>` dans un dossier temporaire, puis emballe et transfère le code. Le clone est supprimé après le déploiement.
193
-
194
- ---
195
-
196
- ## Variables d'environnement
197
-
198
- Les valeurs `${VAR}` ou `{VAR}` dans le YAML sont interpolées depuis l'environnement système.
199
-
200
- ```bash
201
- export XCORE_ADMIN_TOKEN="mon-token-secret"
202
- export XCORE_STAGING_TOKEN="staging-token"
203
- export GITHUB_TOKEN="ghp_..."
204
- export PROD_HOST="prod.monapp.com"
205
- ```
206
-
207
- ---
208
-
209
- ## Ordre d'exécution complet
210
-
211
- ```
212
- hooks.pre_deploy (global)
213
- │
214
- ├─ integration.yaml (si défini)
215
- │ → sftp integration.yaml
216
- │ → POST /config/reload (ou restart service)
217
- │
218
- ├─ Fichiers (section files:)
219
- │ → sftp chaque fichier
220
- │
221
- ├─ Pour chaque extension :
222
- │ extension.hooks.pre_deploy
223
- │ → archive tar.gz
224
- │ → sftp + extraction
225
- │ → POST /services/{name}/restart
226
- │ extension.hooks.post_deploy
227
- │
228
- ├─ Pour chaque plugin :
229
- │ plugin.hooks.pre_deploy
230
- │ → signature HMAC (si sign: true)
231
- │ → archive tar.gz
232
- │ → sftp + extraction
233
- │ → POST /plugins/{name}/reload
234
- │ plugin.hooks.post_deploy
235
- │
236
- hooks.post_deploy (global)
237
- └─ Rapport tableau final
238
- ```
239
-
240
- ---
241
-
242
- ## Hooks
243
-
244
- ### Niveau global
245
-
246
- Définis sous `hooks:` à la racine.
247
-
248
- | Moment | Quand |
249
- |---|---|
250
- | `hooks.pre_deploy` | Avant integration.yaml, fichiers, extensions et plugins |
251
- | `hooks.post_deploy` | Après tous les plugins |
252
-
253
- ### Niveau plugin / extension
254
-
255
- Définis sous `plugins[].hooks` ou `extensions[].hooks`.
256
-
257
- | Moment | Quand |
258
- |---|---|
259
- | `pre_deploy` | Avant l'archivage |
260
- | `post_deploy` | Après le hot-reload / restart |
261
-
262
- ### Options d'un hook
263
-
264
- ```yaml
265
- hooks:
266
- pre_deploy:
267
- - cmd: "ma-commande --option valeur"
268
- cwd: "./sous-dossier" # répertoire d'exécution (défaut : racine projet)
269
- ignore_errors: true # continue même si exit code != 0 (défaut : false)
270
- ```
271
-
272
- !!! warning "Hooks bloquants"
273
- Par défaut (`ignore_errors: false`), un hook qui échoue **annule le déploiement**. Utilise `ignore_errors: true` pour les commandes non-critiques (notifications, rapports...).
274
-
275
- ---
276
-
277
- ## Commandes
278
-
279
- ### `xcli deploy generate`
280
-
281
- Scanne le projet et génère `xcore-deploy.yaml` automatiquement.
282
-
283
- Détecte les plugins (dossiers avec `plugin.yaml`), les extensions (`__init__.py`) et `integration.yaml`. Si le fichier existe déjà, les **targets et hooks sont conservés**.
284
-
285
- ```bash
286
- xcli deploy generate
287
- xcli deploy generate --output deploy/prod.yaml
288
- xcli deploy generate --plugins-dir ./custom-plugins --dry-run
289
- ```
290
-
291
- | Option | Description |
292
- |---|---|
293
- | `--output`, `-o` | Fichier de sortie (défaut: `xcore-deploy.yaml`) |
294
- | `--plugins-dir`, `-p` | Répertoire des plugins (défaut: `./app`) |
295
- | `--extensions-dir`, `-e` | Répertoire des extensions (défaut: `./extensions`) |
296
- | `--dry-run` | Affiche le résultat sans écrire le fichier |
297
-
298
- ---
299
-
300
- ### `xcli deploy init`
301
-
302
- Génère un fichier `xcore-deploy.yaml` d'exemple complet.
303
-
304
- ```bash
305
- xcli deploy init
306
- xcli deploy init --output deploy/prod.yaml
307
- ```
308
-
309
- ---
310
-
311
- ### `xcli deploy list`
312
-
313
- Liste les targets, plugins, extensions, fichiers et hooks déclarés.
314
-
315
- ```bash
316
- xcli deploy list
317
- xcli deploy list --file deploy/prod.yaml
318
- ```
319
-
320
- ---
321
-
322
- ### `xcli deploy run <target>`
323
-
324
- Déploie l'intégralité (integration.yaml + fichiers + extensions + plugins) vers un target.
325
-
326
- ```bash
327
- xcli deploy run production
328
- xcli deploy run staging
329
- ```
330
-
331
- **Options :**
332
-
333
- | Option | Description |
334
- |---|---|
335
- | `--plugin <nom>` | Déploie **uniquement** ce plugin (skip extensions, fichiers et integration) |
336
- | `--dry-run` | Simule sans envoyer ni exécuter de commandes réelles |
337
- | `--no-reload` | Transfère les fichiers sans déclencher reload/restart |
338
- | `--file <chemin>` | Fichier de configuration alternatif |
339
-
340
- ```bash
341
- # Déployer un seul plugin (skip extensions + fichiers + integration)
342
- xcli deploy run production --plugin auth
343
-
344
- # Simuler le déploiement complet
345
- xcli deploy run production --dry-run
346
-
347
- # Transférer sans redémarrer
348
- xcli deploy run production --no-reload
349
-
350
- # Fichier alternatif
351
- xcli deploy run production --file deploy/prod.yaml
352
- ```
353
-
354
- ---
355
-
356
- ### `xcli deploy copy <target> <source> <dest>`
357
-
358
- Copie un fichier vers un serveur distant via SFTP (sans passer par le déploiement complet).
359
-
360
- ```bash
361
- xcli deploy copy production .env /opt/xcore/.env
362
- xcli deploy copy staging config.yaml /opt/xcore/config.yaml --dry-run
363
- xcli deploy copy production docker-compose.yml /opt/xcore/ --file deploy/prod.yaml
364
- ```
365
-
366
- ---
367
-
368
- ### `xcli deploy status <target>`
369
-
370
- Affiche l'état des plugins sur le serveur via l'API XCore.
371
-
372
- ```bash
373
- xcli deploy status production
374
- xcli deploy status staging --file deploy/prod.yaml
375
- ```
376
-
377
- ---
378
-
379
- ## Dépendances requises
380
-
381
- ```bash
382
- pip install paramiko # SSH/SFTP
383
- pip install httpx # Appels API XCore (reload/restart)
384
- # git doit être disponible dans le PATH pour les sources repo
385
- ```
386
-
387
- ---
388
-
389
- ## Exemples de hooks courants
390
-
391
- ```yaml
392
- hooks:
393
- pre_deploy:
394
- - cmd: "uv run xcli plugin security validate --save"
395
- - cmd: "uv run xcli plugin security validate --check-breaking"
396
- - cmd: "uv run pytest tests/ -x -q"
397
- ignore_errors: false
398
-
399
- post_deploy:
400
- - cmd: "uv run xcli deploy status production"
401
- - cmd: >
402
- curl -s -X POST https://hooks.slack.com/services/XXX
403
- -H 'Content-type: application/json'
404
- -d '{"text": "✅ Déploiement production terminé"}'
405
- ignore_errors: true
406
- ```