magicbox-dk 0.0.2.dev1__tar.gz → 1.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 (144) hide show
  1. magicbox_dk-1.0.0/.bumpversion.toml +39 -0
  2. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/CLAUDE.md +33 -12
  3. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/PKG-INFO +62 -1
  4. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/README.md +61 -0
  5. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/_base.py +33 -1
  6. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/dashboard.py +2 -2
  7. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/logs.py +35 -9
  8. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/prepare.py +102 -5
  9. magicbox_dk-0.0.2.dev1/cli/commands/update.py → magicbox_dk-1.0.0/cli/commands/pull.py +4 -4
  10. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/show.py +77 -25
  11. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/start.py +17 -6
  12. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/stop.py +20 -6
  13. magicbox_dk-1.0.0/cli/commands/update.py +140 -0
  14. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/__init__.py +13 -0
  15. magicbox_dk-1.0.0/cli/compose/build_state.py +281 -0
  16. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/builder.py +166 -40
  17. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/healthcheck.py +21 -43
  18. magicbox_dk-1.0.0/cli/compose/logfmt.py +461 -0
  19. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/network.py +63 -12
  20. magicbox_dk-1.0.0/cli/compose/reload.py +117 -0
  21. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/runtime.py +98 -32
  22. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/core/context.py +3 -0
  23. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/core/paths.py +7 -0
  24. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/env.py +111 -4
  25. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/frontend.py +10 -35
  26. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/profile.py +84 -71
  27. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/runnable.py +79 -124
  28. magicbox_dk-1.0.0/cli/editors/sdk.py +190 -0
  29. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/settings.py +79 -0
  30. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/main.py +39 -4
  31. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/models/profile.py +33 -13
  32. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/base.py +24 -4
  33. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/docker.py +37 -4
  34. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/settings.py +65 -0
  35. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/ui.py +95 -34
  36. magicbox_dk-1.0.0/cli/version_check.py +149 -0
  37. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/profile.base.yaml +12 -4
  38. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/back.config.yml +7 -4
  39. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/settings.base.yaml +21 -0
  40. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/redis/docker-compose.yml +10 -1
  41. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/s3/docker-compose.yml +7 -1
  42. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/surrealdb/docker-compose.yml +7 -1
  43. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/profile.example.yaml +13 -6
  44. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/pyproject.toml +1 -1
  45. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/uv.lock +1 -1
  46. magicbox_dk-0.0.2.dev1/.bumpversion.toml +0 -53
  47. magicbox_dk-0.0.2.dev1/cli/commands/version.py +0 -30
  48. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/.github/workflows/ci.yml +0 -0
  49. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/.github/workflows/cleanup-prereleases.yml +0 -0
  50. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/.github/workflows/release.yml +0 -0
  51. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/.gitignore +0 -0
  52. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/LICENSE +0 -0
  53. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/__init__.py +0 -0
  54. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/cleanup.py +0 -0
  55. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/__init__.py +0 -0
  56. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/clean.py +0 -0
  57. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/create.py +0 -0
  58. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/credentials.py +0 -0
  59. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/delete.py +0 -0
  60. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/doctor.py +0 -0
  61. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/edit.py +0 -0
  62. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/env.py +0 -0
  63. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/init.py +0 -0
  64. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/list.py +0 -0
  65. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/restart.py +0 -0
  66. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/settings.py +0 -0
  67. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/shell.py +0 -0
  68. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/status.py +0 -0
  69. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/switch.py +0 -0
  70. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/commands/validate.py +0 -0
  71. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/compose/templates.py +0 -0
  72. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/core/__init__.py +0 -0
  73. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/core/cmd.py +0 -0
  74. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/core/profile_io.py +0 -0
  75. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/debug.py +0 -0
  76. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/__init__.py +0 -0
  77. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/_readiness.py +0 -0
  78. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/_state.py +0 -0
  79. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/infra.py +0 -0
  80. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/kin.py +0 -0
  81. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/editors/profile_meta.py +0 -0
  82. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/env/__init__.py +0 -0
  83. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/env/dotenv.py +0 -0
  84. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/env/loaders.py +0 -0
  85. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/env/regenerate.py +0 -0
  86. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/env/resolver.py +0 -0
  87. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/models/__init__.py +0 -0
  88. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/models/env.py +0 -0
  89. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/models/service.py +0 -0
  90. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/__init__.py +0 -0
  91. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/binaries.py +0 -0
  92. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/git.py +0 -0
  93. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/process.py +0 -0
  94. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/cli/runner/redaction.py +0 -0
  95. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/credentials.base.yaml +0 -0
  96. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/globals.base.yaml +0 -0
  97. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/chainlit.config.yml +0 -0
  98. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/horizon.config.yml +0 -0
  99. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/module.config.yml +0 -0
  100. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/node-service-provider.config.yml +0 -0
  101. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/s3.config.yml +0 -0
  102. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/configs/services/surrealdb.config.yml +0 -0
  103. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/archetypes/docker-compose.yml +0 -0
  104. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/back/docker-compose.yml +0 -0
  105. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/chainlit/docker-compose.yml +0 -0
  106. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/docker-compose.yml +0 -0
  107. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/horizon/docker-compose.yml +0 -0
  108. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/docker/node-service-provider/docker-compose.yml +0 -0
  109. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/Dockerfile/Dockerfile +0 -0
  110. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/Dockerfile/digitalkin-1.0.0.dev0.tar.gz +0 -0
  111. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/Dockerfile/entrypoint.sh +0 -0
  112. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/Dockerfile/generate_certificates.py +0 -0
  113. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/README.md +0 -0
  114. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/__init__.py +0 -0
  115. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/application.py +0 -0
  116. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/config.py +0 -0
  117. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/handlers/__init__.py +0 -0
  118. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/handlers/input_factory.py +0 -0
  119. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/handlers/output_handler.py +0 -0
  120. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/main.py +0 -0
  121. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/models/__init__.py +0 -0
  122. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/models/config.py +0 -0
  123. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/models/protocols.py +0 -0
  124. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/pyproject.toml +0 -0
  125. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/__init__.py +0 -0
  126. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/filesystem.py +0 -0
  127. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/gateway_client.py +0 -0
  128. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/module_client.py +0 -0
  129. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/registry.py +0 -0
  130. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/services/setup.py +0 -0
  131. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/chainlit/uv.lock +0 -0
  132. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/horizon/Dockerfile/Dockerfile +0 -0
  133. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/services/horizon/Dockerfile/nginx.conf +0 -0
  134. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/conftest.py +0 -0
  135. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_base.py +0 -0
  136. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_binaries.py +0 -0
  137. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_docker.py +0 -0
  138. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_docker_validators.py +0 -0
  139. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_git.py +0 -0
  140. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_git_repo_ops.py +0 -0
  141. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_git_validators.py +0 -0
  142. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_process.py +0 -0
  143. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_redaction.py +0 -0
  144. {magicbox_dk-0.0.2.dev1 → magicbox_dk-1.0.0}/tests/test_settings.py +0 -0
@@ -0,0 +1,39 @@
1
+ # bump-my-version configuration
2
+ # Semantic Versioning : major.minor.patch — https://semver.org
3
+ # Docs : https://callowayproject.github.io/bump-my-version/
4
+
5
+ [tool.bumpversion]
6
+ current_version = "1.0.0"
7
+
8
+ allow_dirty = false # Require a clean working tree
9
+ commit = true # Auto-commit the version bump
10
+ tag = true # Auto-create the git tag
11
+ sign_tags = true # GPG-sign the tag (git tag -s, uses user.signingkey)
12
+ tag_name = "v{new_version}" # e.g. v0.0.5
13
+
14
+ # Plain major.minor.patch — no pre-release / build metadata.
15
+ parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'
16
+ serialize = ["{major}.{minor}.{patch}"]
17
+
18
+ # --- Files kept in sync on every bump ------------------------------------
19
+
20
+ # pyproject.toml : [project] version. (The bump-my-version config lives in
21
+ # this separate file, so [project].version is NOT touched natively — this
22
+ # explicit block matches the single unambiguous line.)
23
+ [[tool.bumpversion.files]]
24
+ filename = "pyproject.toml"
25
+ search = 'version = "{current_version}"'
26
+ replace = 'version = "{new_version}"'
27
+
28
+ # uv.lock : the editable magicbox-dk package entry.
29
+ [[tool.bumpversion.files]]
30
+ filename = "uv.lock"
31
+ regex = true
32
+ search = 'name = "magicbox-dk"\nversion = "{current_version}"'
33
+ replace = 'name = "magicbox-dk"\nversion = "{new_version}"'
34
+
35
+ # Usage:
36
+ # bump-my-version bump patch # 0.0.4 -> 0.0.5
37
+ # bump-my-version bump minor # 0.0.4 -> 0.1.0
38
+ # bump-my-version bump major # 0.0.4 -> 1.0.0
39
+ # bump-my-version show-bump # preview the next versions
@@ -42,7 +42,8 @@ The CLI is organized in thematic sub-packages — no flat catch-all. Each packag
42
42
  `INFRA_PORTS`/`INFRA_SCHEMES`/`INFRA_PATH_SUFFIXES`) AND user-configurable
43
43
  values (instance fields : `ports` — **uniquement** `frontend_host` (port hôte unique partagé Chainlit/Horizon) +
44
44
  `archetype_pool_start`/`_end` ;
45
- `timeouts`, `docker`, `start`, `service_repos`, `env`, `surrealdb_logins`,
45
+ `timeouts`, `docker`, `start`, `logs` (champs affichés par `dk logs` — modèle `LogDisplay`, tous `True` par défaut ;
46
+ conteneur + message toujours affichés), `service_repos`, `env`, `surrealdb_logins`,
46
47
  `s3_accounts`). Type aliases `Mode`, `InfraMode`, `Section` and base class `_Strict` are exported here. Models `SurrealdbLogin` and `S3Account`
47
48
  (credentials profiles shared across profiles) live here too. `Settings.load(yaml_path)` / `Settings.save(yaml_path)` round-trip a snapshot of
48
49
  configurable fields to `<config_root>/settings.yaml`.
@@ -77,10 +78,12 @@ secrets, nettoyage des PID sur signaux.
77
78
  Point d'entrée : `from cli.runner import docker, git` (singletons).
78
79
 
79
80
  - `cli/runner/base.py` — `Cmd` (ABC) + `CmdError` + `CmdResult`.
80
- `_run(args, *, timeout, check, capture, cwd, on_progress, progress_re)` avec 4 modes
81
+ `_run(args, *, timeout, check, capture, cwd, on_progress, progress_re, on_output, on_interrupt, on_line)` avec 4 modes
81
82
  de capture : `query` (capture stdout+stderr ; echo en debug), `drain` (thread drainer anti-deadlock), `pty` (
82
83
  pseudo-TTY pour la progression BuildKit,
83
- POSIX ; fallback `drain` sur Windows), `inherit` (sortie directe, interactif).
84
+ POSIX ; fallback `drain` sur Windows), `inherit` (sortie directe, interactif). `on_line` (mode `drain`) : callback
85
+ **par ligne** au fil de l'eau, **sans** accumulation (mémoire bornée pour un flux non borné, ex. `logs --follow`
86
+ reformaté par `LogPrettifier`) ; préserve `drain` même en debug.
84
87
  - `cli/runner/binaries.py` — `resolve_binary(tool)` (candidats absolus par OS → `shutil.which` fallback, cache) +
85
88
  `sanitized_path(binary)`. Auto-détection
86
89
  seule (pas d'override settings).
@@ -118,7 +121,7 @@ Point d'entrée : `from cli.runner import docker, git` (singletons).
118
121
  schéma non autorisé). Primitives validées
119
122
  (`status_porcelain`, `head_branch`, `rev_list_counts`…, `clone`/`fetch`/`checkout`/`pull_ff`) **et** orchestration UI
120
123
  repliée depuis l'ancien `git_ops`
121
- (`sync_repo`/`pull_repo`/`repo_status` + `RepoStatus`/`report_repo_statuses`). Consommé par `dk prepare`/`update`/
124
+ (`sync_repo`/`pull_repo`/`repo_status` + `RepoStatus`/`report_repo_statuses`). Consommé par `dk prepare`/`pull`/
122
125
  `start`.
123
126
 
124
127
  ### `cli/core/` — runtime state
@@ -176,7 +179,22 @@ All models inherit from `cli.settings._Strict` (one shared base with `extra="for
176
179
  `project_built_images`/`compose_config_images`/`container_restart_counts` (parsing des sorties docker), health
177
180
  snapshot, `wait_until_healthy`,
178
181
  `report_compose_failure` (masque les secrets via `cli.runner.redaction`), `compute_compose_env`/`compose_env_context`,
179
- `follow_logs`/`dump_logs`.
182
+ `follow_logs`/`dump_logs` (branchent la surcouche `LogPrettifier` par défaut ; `raw=True` = sortie docker brute).
183
+ - `cli/compose/logfmt.py` — `LogPrettifier` : **surcouche d'affichage** des logs Compose. Réassemble le JSON structuré
184
+ multi-lignes **par conteneur** (dé-multiplexage via les préfixes `<name> |` de `docker compose logs` ; parse en
185
+ `json.loads(strict=False)` — les tracebacks du champ `exception` ont de **vrais retours à la ligne**, JSON
186
+ techniquement
187
+ invalide). Le **nom du conteneur est toujours en tête** (façon `docker`), **padé à une largeur commune** (plafonnée) →
188
+ le `│` séparateur tombe à la **même colonne pour tous les conteneurs** et se répète en tête des lignes de
189
+ continuation.
190
+ Ligne principale (`conteneur │ heure · niveau · source sdk/module · module · fichier:ligne · fonction · extra` — méta
191
+ primaire ET secondaire), puis ligne(s) message **en gras** (JSON embarqué → indenté) et traceback (`│` de
192
+ continuation).
193
+ Le non-JSON (infra, watcher hot reload `dk-reload`/entrypoint en dev) est rendu au même format `conteneur │ texte`.
194
+ Colore par niveau ET par conteneur (couleur stable). Les champs (sauf conteneur/message) sont pilotés par
195
+ `settings.logs` (`LogDisplay`) — `dk settings → Logs`. Laisse passer le non-JSON (infra) en brut. Stateful : une
196
+ instance par flux, `feed(ligne)` branché sur le `on_line` du runner (cf. `Docker.compose_logs`), `flush()` en fin de
197
+ flux.
180
198
  - `cli/compose/network.py` — ports + allocators (`find_free_port`, `port_is_free`, `allocate_api_port`, `allocate_archetype_port`), Docker naming (
181
199
  `docker_safe_name`, `container_name`), Pydantic `Network`/`ServiceAddress`, `build_network`, `address_env_vars`, `reserved_var_names`,
182
200
  `write_network_yaml`/`read_network_yaml`. Constants from `Settings.ports`, the CLI-managed infra ClassVars (
@@ -205,7 +223,8 @@ the top of each menu :
205
223
  - `cli/editors/env.py` — `run_env_editor` (the `<entry>.yml` editor — 4 sections, secret masking, Jinja resolution
206
224
  preview, network
207
225
  read-only). Keyboard shortcuts a/g/i/d/D/r/?/h/b/Esc preserved.
208
- - `cli/editors/settings.py` — `SettingsEditor(ctx).run()` covers Env globales, Start defaults, Ports, Timeouts, Docker, Infra. All editable via menus,
226
+ - `cli/editors/settings.py` — `SettingsEditor(ctx).run()` covers Env globales, Start defaults, Logs (champs affichés par
227
+ `dk logs`), Ports, Timeouts, Docker, Infra. All editable via menus,
209
228
  persisted via `ctx.save_settings()`.
210
229
  - `cli/editors/_state.py` — internal helpers shared by editors (`_PendingEnv`, `_fmt_value`, diff utilities).
211
230
 
@@ -238,16 +257,16 @@ class DeleteCommand(BaseCommand):
238
257
  `cli` est **l'unique méthode publique** : elle construit l'instance depuis la CLI
239
258
  et déclenche `_dispatch()` (le cycle de vie partagé). `BaseCommand` fournit un
240
259
  **`cli` par défaut** (classmethod `cls()._dispatch()`) : une commande **sans
241
- argument** (`version`, `dashboard`, `settings`) ne redéfinit pas `cli`, elle
260
+ argument** (`dashboard`, `settings`) ne redéfinit pas `cli`, elle
242
261
  hérite du défaut (on passe `help=` au montage pour garder une description
243
- distincte : `app.command("version", help="…")(VersionCommand.cli)`). Toute
262
+ distincte : `app.command("dashboard", help="…")(DashboardCommand.cli)`). Toute
244
263
  commande avec arguments/options **redéfinit** `cli` en `@staticmethod` typée.
245
264
 
246
265
  - `cli/commands/_base.py` — `BaseCommand` (ABC). Cycle de vie via attributs de
247
266
  classe surchargeables : `requires_profile` (bootstrap vs bootstrap_no_profile),
248
267
  `require_existing`, `require_prepared`, `requires_init` (False ⇒ pas de
249
268
  `require_initialized`, ex. `init`/`dashboard`/`doctor`), `loads_context`
250
- (False ⇒ aucun contexte, ex. `version`). `_dispatch()` fait le préambule +
269
+ (False ⇒ aucun contexte, ex. `update`). `_dispatch()` fait le préambule +
251
270
  `run()`, et enveloppe `run()` d'une **frontière `CmdError`** (échec d'une
252
271
  commande externe `check=True` → panneau d'erreur, sortie déjà masquée).
253
272
  Helpers : `fail(msg, code=, cause=)`, `confirm(msg, yes=)`,
@@ -293,12 +312,14 @@ Verbs (with aliases) :
293
312
  | `list, ls` | List profiles (`--json` supported). |
294
313
  | `show, info [profile]` | Compact profile config view (`--json` supported). |
295
314
  | `status, stats, ps` | Container state, section by section. |
296
- | `logs [service]` | `docker compose logs`. |
315
+ | `logs [service]` | `docker compose logs` reformatés/colorés (JSON structuré → 2 lignes) ; `--raw` = brut. |
297
316
  | `shell, exec <service>` | `docker exec -it` into a container of the active profile. |
298
- | `update [name...]` | `git pull --ff-only` on clones of the active profile. |
317
+ | `pull, sync [name...]` | `git pull --ff-only` on clones of the active profile. |
299
318
  | `validate [profile]` | Validate YAML (Pydantic), no side effects. |
300
319
  | `doctor` | Check Docker, Compose, git, user structure. |
301
- | `version` | Print Magicbox version. |
320
+ | `update [--check]` | Update the CLI itself (`magicbox-dk`) from PyPI. |
321
+
322
+ The root `dk --version` (`-V`) prints the current CLI version and exits (there is no `version` sub-command).
302
323
 
303
324
  The entrypoint `dk = "cli.main:app"` is declared in `pyproject.toml`.
304
325
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: magicbox-dk
3
- Version: 0.0.2.dev1
3
+ Version: 1.0.0
4
4
  Summary: Magicbox for help DigitalKin developpers.
5
5
  Author-email: Alexandre TRESALLET <a.tresall@digitalkin.ai>
6
6
  License-Expression: MIT
@@ -41,6 +41,7 @@ stack — le tout stocké hors du repo, dans le dossier de config standard de vo
41
41
  - [Settings, globals & credentials](#settings-globals--credentials)
42
42
  - [Multi-profils](#multi-profils)
43
43
  - [Auth git](#auth-git)
44
+ - [Versioning & release](#versioning--release)
44
45
  - [Dépannage](#dépannage)
45
46
  - [License](#license)
46
47
 
@@ -304,6 +305,66 @@ Magicbox délègue l'authentification au système : configurez votre credential
304
305
 
305
306
  ---
306
307
 
308
+ ## Versioning & release
309
+
310
+ Le versionnage suit **PEP 440** : `major.minor.patch` avec un pré-release `.devN` optionnel,
311
+ piloté par [`bump-my-version`](https://github.com/callowayproject/bump-my-version) (config dans
312
+ `.bumpversion.toml`). Chaque `bump` met à jour `pyproject.toml` **et** `uv.lock`, puis **commit +
313
+ tag** automatiquement (`commit = true`, `tag = true`).
314
+
315
+ > Le binaire Homebrew de `bump-my-version` peut être cassé (interpréteur Python obsolète) —
316
+ > préfixe les commandes par `uv run` pour utiliser celui du venv.
317
+
318
+ **Règle d'or** : un `.devN` est toujours un pré-release de la **prochaine** version pas encore
319
+ sortie (`0.0.2.dev1 < 0.0.2`). La base `major.minor.patch` ne fait que **monter** — on ne colle
320
+ jamais un `.dev` sur une version déjà publiée.
321
+
322
+ ### Les cas
323
+
324
+ | Cas | Commande | Exemple |
325
+ |-----------------------------------------------|------------------------------------|-----------------------------|
326
+ | **Ouvrir un cycle dev** (depuis une finale) | `bump patch` \| `minor` \| `major` | `0.0.1` → `0.0.2.dev1` |
327
+ | **Itérer en dev** | `bump dev` | `0.0.2.dev1` → `0.0.2.dev2` |
328
+ | **Passer d'une dev à la release** (finaliser) | `bump --new-version X.Y.Z` | `0.0.2.dev2` → `0.0.2` |
329
+
330
+ > `bump dev` depuis une **finale** échoue (`value 0 is lower than the first value 1`) : c'est voulu
331
+ > (`first_value = 1`). Depuis une finale, on ouvre le cycle avec `patch`/`minor`/`major`, jamais `dev`.
332
+ > Et « finaliser » (retirer le `.dev`) se fait avec `--new-version`, car un compteur `.dev` ne peut
333
+ > pas redescendre à 0 tout seul.
334
+
335
+ ### Procédure complète (pour chaque version)
336
+
337
+ ```bash
338
+ # 1. bump : édite pyproject.toml + uv.lock, commit + tag automatiques
339
+ uv run bump-my-version bump patch # 0.0.1 → 0.0.2.dev1
340
+
341
+ # 2. pousse le commit ET son tag
342
+ git push --follow-tags origin main
343
+
344
+ # 3. crée la GitHub Release → déclenche la publication (.github/workflows/release.yml)
345
+ gh release create v0.0.2.dev1 --prerelease --generate-notes # --prerelease pour un .dev
346
+ ```
347
+
348
+ Exemple d'un cycle complet `0.0.1 → 0.0.2` :
349
+
350
+ ```bash
351
+ uv run bump-my-version bump patch # 0.0.1 → 0.0.2.dev1
352
+ git push --follow-tags origin main
353
+ gh release create v0.0.2.dev1 --prerelease --generate-notes
354
+
355
+ uv run bump-my-version bump dev # 0.0.2.dev1 → 0.0.2.dev2
356
+ git push --follow-tags origin main
357
+ gh release create v0.0.2.dev2 --prerelease --generate-notes
358
+
359
+ uv run bump-my-version bump --new-version 0.0.2 # finalise : 0.0.2.dev2 → 0.0.2
360
+ git push --follow-tags origin main
361
+ gh release create v0.0.2 --generate-notes # release finale (sans --prerelease)
362
+ ```
363
+
364
+ `bump-my-version show-bump` affiche à tout moment les transitions possibles depuis la version courante.
365
+
366
+ ---
367
+
307
368
  ## Dépannage
308
369
 
309
370
  | Symptôme | Remède |
@@ -24,6 +24,7 @@ stack — le tout stocké hors du repo, dans le dossier de config standard de vo
24
24
  - [Settings, globals & credentials](#settings-globals--credentials)
25
25
  - [Multi-profils](#multi-profils)
26
26
  - [Auth git](#auth-git)
27
+ - [Versioning & release](#versioning--release)
27
28
  - [Dépannage](#dépannage)
28
29
  - [License](#license)
29
30
 
@@ -287,6 +288,66 @@ Magicbox délègue l'authentification au système : configurez votre credential
287
288
 
288
289
  ---
289
290
 
291
+ ## Versioning & release
292
+
293
+ Le versionnage suit **PEP 440** : `major.minor.patch` avec un pré-release `.devN` optionnel,
294
+ piloté par [`bump-my-version`](https://github.com/callowayproject/bump-my-version) (config dans
295
+ `.bumpversion.toml`). Chaque `bump` met à jour `pyproject.toml` **et** `uv.lock`, puis **commit +
296
+ tag** automatiquement (`commit = true`, `tag = true`).
297
+
298
+ > Le binaire Homebrew de `bump-my-version` peut être cassé (interpréteur Python obsolète) —
299
+ > préfixe les commandes par `uv run` pour utiliser celui du venv.
300
+
301
+ **Règle d'or** : un `.devN` est toujours un pré-release de la **prochaine** version pas encore
302
+ sortie (`0.0.2.dev1 < 0.0.2`). La base `major.minor.patch` ne fait que **monter** — on ne colle
303
+ jamais un `.dev` sur une version déjà publiée.
304
+
305
+ ### Les cas
306
+
307
+ | Cas | Commande | Exemple |
308
+ |-----------------------------------------------|------------------------------------|-----------------------------|
309
+ | **Ouvrir un cycle dev** (depuis une finale) | `bump patch` \| `minor` \| `major` | `0.0.1` → `0.0.2.dev1` |
310
+ | **Itérer en dev** | `bump dev` | `0.0.2.dev1` → `0.0.2.dev2` |
311
+ | **Passer d'une dev à la release** (finaliser) | `bump --new-version X.Y.Z` | `0.0.2.dev2` → `0.0.2` |
312
+
313
+ > `bump dev` depuis une **finale** échoue (`value 0 is lower than the first value 1`) : c'est voulu
314
+ > (`first_value = 1`). Depuis une finale, on ouvre le cycle avec `patch`/`minor`/`major`, jamais `dev`.
315
+ > Et « finaliser » (retirer le `.dev`) se fait avec `--new-version`, car un compteur `.dev` ne peut
316
+ > pas redescendre à 0 tout seul.
317
+
318
+ ### Procédure complète (pour chaque version)
319
+
320
+ ```bash
321
+ # 1. bump : édite pyproject.toml + uv.lock, commit + tag automatiques
322
+ uv run bump-my-version bump patch # 0.0.1 → 0.0.2.dev1
323
+
324
+ # 2. pousse le commit ET son tag
325
+ git push --follow-tags origin main
326
+
327
+ # 3. crée la GitHub Release → déclenche la publication (.github/workflows/release.yml)
328
+ gh release create v0.0.2.dev1 --prerelease --generate-notes # --prerelease pour un .dev
329
+ ```
330
+
331
+ Exemple d'un cycle complet `0.0.1 → 0.0.2` :
332
+
333
+ ```bash
334
+ uv run bump-my-version bump patch # 0.0.1 → 0.0.2.dev1
335
+ git push --follow-tags origin main
336
+ gh release create v0.0.2.dev1 --prerelease --generate-notes
337
+
338
+ uv run bump-my-version bump dev # 0.0.2.dev1 → 0.0.2.dev2
339
+ git push --follow-tags origin main
340
+ gh release create v0.0.2.dev2 --prerelease --generate-notes
341
+
342
+ uv run bump-my-version bump --new-version 0.0.2 # finalise : 0.0.2.dev2 → 0.0.2
343
+ git push --follow-tags origin main
344
+ gh release create v0.0.2 --generate-notes # release finale (sans --prerelease)
345
+ ```
346
+
347
+ `bump-my-version show-bump` affiche à tout moment les transitions possibles depuis la version courante.
348
+
349
+ ---
350
+
290
351
  ## Dépannage
291
352
 
292
353
  | Symptôme | Remède |
@@ -21,6 +21,7 @@ est délégué à :class:`cli.ui.StepReporter` exposé via ``self.steps``.
21
21
  from __future__ import annotations
22
22
 
23
23
  import itertools
24
+ import sys
24
25
  import threading
25
26
  import time
26
27
  from abc import ABC, abstractmethod
@@ -32,6 +33,7 @@ from typing import Annotated, Any, NoReturn, TypeVar
32
33
  import questionary
33
34
  import typer
34
35
 
36
+ from cli import version_check
35
37
  from cli.core.cmd import bootstrap, bootstrap_no_profile, resolve_target
36
38
  from cli.core.context import MagicboxContext
37
39
  from cli.debug import dlog, set_debug, set_verbose
@@ -77,6 +79,10 @@ class BaseCommand(ABC):
77
79
  #: commandes « profil courant » (``start``/``edit``/``prepare``…) gardent
78
80
  #: ``False`` (défaut → profil actif, pas de prompt).
79
81
  picks_profile: bool = False
82
+ #: ``True`` ⇒ affiche (sur stderr, TTY uniquement) une ligne d'info si une
83
+ #: version plus récente est publiée sur PyPI. Désactivé sur ``version`` (qui
84
+ #: l'affiche à sa façon) et ``update`` (c'est déjà la mise à jour du CLI).
85
+ notifies_upgrade: bool = True
80
86
 
81
87
  def __init__(
82
88
  self, profile: str | None = None, *,
@@ -119,6 +125,13 @@ class BaseCommand(ABC):
119
125
  # Verbose déroule le détail des étapes (cf. ``-v/--verbose``) — posé avant
120
126
  # tout pour couvrir aussi le préambule. ``set_debug`` est géré par bootstrap.
121
127
  set_verbose(self.verbose)
128
+ # Vérif de version : uniquement en terminal interactif (jamais en
129
+ # script/CI/pipe). Le rafraîchissement du cache est lancé en tâche de
130
+ # fond ici (max de temps pour finir pendant `run`) ; la notice, lue au
131
+ # cache, est affichée après un `run` réussi.
132
+ notify_upgrade = self.notifies_upgrade and sys.stderr.isatty()
133
+ if notify_upgrade:
134
+ version_check.trigger_background_refresh()
122
135
  if self.requires_profile:
123
136
  self.ctx, self.profile_id = bootstrap(
124
137
  self.profile_name,
@@ -140,6 +153,10 @@ class BaseCommand(ABC):
140
153
 
141
154
  try:
142
155
  self.run()
156
+ if notify_upgrade:
157
+ notice = version_check.notice_if_outdated()
158
+ if notice:
159
+ typer.secho(notice, fg=typer.colors.YELLOW, err=True)
143
160
  except CmdError as exc:
144
161
  # Échec d'une commande externe en mode ``check=True`` (git/docker).
145
162
  # ``exc.output`` est déjà masqué des secrets par le runner.
@@ -151,7 +168,13 @@ class BaseCommand(ABC):
151
168
  # sous-process encore vivants, puis on indique CLAIREMENT ce qui s'est
152
169
  # passé (l'utilisateur ne doit pas se demander si ça tourne en fond).
153
170
  process.terminate_all(grace=2.0)
154
- self.steps.panel_warn("Interrompu", self._interrupt_note())
171
+ # Le terminal a échoté ``^C`` à la position du curseur : on efface la
172
+ # ligne courante (retour chariot + clear) avant le panneau, sinon son
173
+ # cadre est décalé de 2 colonnes (TTY uniquement).
174
+ if sys.stdout.isatty():
175
+ sys.stdout.write("\r\033[K")
176
+ sys.stdout.flush()
177
+ self._render_interrupt()
155
178
  raise typer.Exit(code=130) from None
156
179
 
157
180
  @abstractmethod
@@ -169,6 +192,15 @@ class BaseCommand(ABC):
169
192
  """
170
193
  return None
171
194
 
195
+ def _render_interrupt(self) -> None:
196
+ """Panneau affiché sur Ctrl+C. Par défaut : ``⚠ Interrompu`` (jaune) + note.
197
+
198
+ Surchargeable pour changer le ton (titre / couleur / détail). Ex. ``dk
199
+ logs`` où Ctrl+C est la fermeture **volontaire** du flux : un panneau
200
+ neutre sans note suffit (cf. ``LogsCommand._render_interrupt``).
201
+ """
202
+ self.steps.panel_warn("Interrompu", self._interrupt_note())
203
+
172
204
  def resolve_target(self) -> str:
173
205
  """Résout le profil ciblé pour une commande à résolution manuelle.
174
206
 
@@ -14,9 +14,9 @@ import typer
14
14
  import yaml
15
15
 
16
16
  from cli.commands._base import BaseCommand
17
- from cli.commands.version import package_version
18
17
  from cli.core.context import MagicboxContext
19
18
  from cli.ui import GREY_FG, Report, short_home_path
19
+ from cli.version_check import current_version
20
20
 
21
21
  # Sous-commandes mises en avant dans le mémo de démarrage (verbe → résumé).
22
22
  QUICK_COMMANDS: tuple[tuple[str, str], ...] = (
@@ -42,7 +42,7 @@ class DashboardCommand(BaseCommand):
42
42
  # ── En-tête : titre + description ─────────────────────────────────── #
43
43
  r.blank()
44
44
  title = typer.style("Magicbox", fg=typer.colors.CYAN, bold=True)
45
- ver = typer.style(f"v{package_version()}", fg=GREY_FG)
45
+ ver = typer.style(f"v{current_version()}", fg=GREY_FG)
46
46
  typer.echo(f" {title} · {ver}")
47
47
  r.detail(
48
48
  "Orchestrateur d'environnements de dev pour les services & archetypes DigitalKin.",
@@ -35,14 +35,18 @@ class LogsCommand(BaseCommand):
35
35
  services: list[str] | None = None,
36
36
  follow: bool = True,
37
37
  tail: int = 0,
38
+ raw: bool = False,
38
39
  debug: bool = False,
39
40
  ) -> None:
40
41
  super().__init__(profile, profile_id=profile_id, debug=debug)
41
42
  self.services = list(services or [])
42
43
  self.follow = follow
43
44
  self.tail = tail
45
+ self.raw = raw
44
46
 
45
47
  def run(self) -> None:
48
+ from cli.compose.logfmt import LogPrettifier
49
+
46
50
  profile = load_profile(self.ctx, self.profile_id)
47
51
 
48
52
  # Rien fourni en argument : sur un terminal interactif, on ouvre un
@@ -55,18 +59,33 @@ class LogsCommand(BaseCommand):
55
59
  typer.echo("Annulé.")
56
60
  return
57
61
 
62
+ # Surcouche lisible par défaut ; ``--raw`` rend la sortie docker brute.
63
+ # Les champs affichés suivent ``settings.logs`` (dk settings → Logs).
64
+ prettifier = None if self.raw else LogPrettifier(self.ctx.settings.logs)
65
+ on_line = prettifier.feed if prettifier is not None else None
66
+
58
67
  project = self.ctx.compose_project(self.profile_id)
59
68
  files, profiles = compose_args_for(
60
69
  profile, self.ctx.paths.profile_overrides_dir(self.profile_id),
61
70
  )
62
71
  compose_env = compute_compose_env(self.ctx, profile, self.profile_id)
63
- with compose_env_context(compose_env):
64
- docker.compose_logs(
65
- project, files, profiles,
66
- follow=self.follow,
67
- tail=self.tail if self.tail > 0 else None,
68
- services=services or None,
69
- )
72
+ try:
73
+ with compose_env_context(compose_env):
74
+ docker.compose_logs(
75
+ project, files, profiles,
76
+ follow=self.follow,
77
+ tail=self.tail if self.tail > 0 else None,
78
+ services=services or None,
79
+ on_line=on_line,
80
+ )
81
+ finally:
82
+ if prettifier is not None:
83
+ prettifier.flush()
84
+
85
+ def _render_interrupt(self) -> None:
86
+ # Ctrl+C sur `dk logs` = fermeture volontaire du flux, pas un incident :
87
+ # panneau neutre « Interrompu » sans description (couleur ≠ jaune d'alerte).
88
+ self.steps.panel_info("Interrompu")
70
89
 
71
90
  @staticmethod
72
91
  def cli(
@@ -95,12 +114,19 @@ class LogsCommand(BaseCommand):
95
114
  int,
96
115
  typer.Option("--tail", "-n", help="Lignes depuis la fin."),
97
116
  ] = 0,
117
+ raw: Annotated[
118
+ bool,
119
+ typer.Option("--raw", help="Sortie docker brute (désactive la mise en forme lisible)."),
120
+ ] = False,
98
121
  debug: Annotated[
99
122
  bool,
100
123
  typer.Option("--debug", "-d", help="Logs détaillés."),
101
124
  ] = False,
102
125
  ) -> None:
103
- """Suit les logs Compose du profil.
126
+ """Suit les logs Compose du profil, reformatés pour la lisibilité.
127
+
128
+ Les logs JSON structurés des modules sont recomposés en deux lignes
129
+ (méta colorée + message) ; ``--raw`` rend la sortie docker brute.
104
130
 
105
131
  ``dk logs`` sans argument ouvre un menu multi-sélection des services
106
132
  (ou « Tous ») sur un terminal interactif. ``dk logs back node-service-provider``
@@ -108,7 +134,7 @@ class LogsCommand(BaseCommand):
108
134
  """
109
135
  LogsCommand(
110
136
  profile_name, profile_id=profile_id, services=services, follow=follow,
111
- tail=tail, debug=debug,
137
+ tail=tail, raw=raw, debug=debug,
112
138
  )._dispatch()
113
139
 
114
140