splent-cli 1.5.0__tar.gz → 1.5.1__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 (163) hide show
  1. {splent_cli-1.5.0/src/splent_cli.egg-info → splent_cli-1.5.1}/PKG-INFO +1 -1
  2. {splent_cli-1.5.0 → splent_cli-1.5.1}/pyproject.toml +1 -1
  3. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_migrate.py +6 -33
  4. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_rollback.py +22 -1
  5. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_contract.py +4 -0
  6. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_create.py +4 -0
  7. splent_cli-1.5.1/src/splent_cli/commands/feature/feature_refinement.py +879 -0
  8. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_release.py +33 -18
  9. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_xray.py +206 -181
  10. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_build.py +25 -9
  11. splent_cli-1.5.1/src/splent_cli/commands/product/product_deploy.py +274 -0
  12. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_deselect.py +9 -4
  13. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_env.py +1 -3
  14. splent_cli-1.5.1/src/splent_cli/commands/product/product_restart.py +114 -0
  15. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/tokens.py +4 -1
  16. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/services/compose.py +5 -3
  17. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/services/context.py +3 -3
  18. {splent_cli-1.5.0 → splent_cli-1.5.1/src/splent_cli.egg-info}/PKG-INFO +1 -1
  19. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli.egg-info/SOURCES.txt +1 -0
  20. splent_cli-1.5.0/src/splent_cli/commands/product/product_deploy.py +0 -173
  21. splent_cli-1.5.0/src/splent_cli/commands/product/product_restart.py +0 -64
  22. {splent_cli-1.5.0 → splent_cli-1.5.1}/LICENSE +0 -0
  23. {splent_cli-1.5.0 → splent_cli-1.5.1}/README.md +0 -0
  24. {splent_cli-1.5.0 → splent_cli-1.5.1}/setup.cfg +0 -0
  25. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/__init__.py +0 -0
  26. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/__main__.py +0 -0
  27. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/cli.py +0 -0
  28. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/__init__.py +0 -0
  29. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/__init__.py +0 -0
  30. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_clear.py +0 -0
  31. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_orphans.py +0 -0
  32. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_outdated.py +0 -0
  33. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_prune.py +0 -0
  34. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_size.py +0 -0
  35. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_status.py +0 -0
  36. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_usage.py +0 -0
  37. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/cache/cache_versions.py +0 -0
  38. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/__init__.py +0 -0
  39. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_deps.py +0 -0
  40. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_docker.py +0 -0
  41. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_env.py +0 -0
  42. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_features.py +0 -0
  43. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_github.py +0 -0
  44. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_infra.py +0 -0
  45. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_product.py +0 -0
  46. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_pypi.py +0 -0
  47. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/check/check_pyproject.py +0 -0
  48. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/clear_cache.py +0 -0
  49. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/clear_log.py +0 -0
  50. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/clear_uploads.py +0 -0
  51. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/command_create.py +0 -0
  52. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/coverage.py +0 -0
  53. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_console.py +0 -0
  54. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_dump.py +0 -0
  55. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_reset.py +0 -0
  56. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_restore.py +0 -0
  57. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_seed.py +0 -0
  58. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_status.py +0 -0
  59. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/database/db_upgrade.py +0 -0
  60. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/doctor.py +0 -0
  61. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/env/env_list.py +0 -0
  62. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/env/env_set.py +0 -0
  63. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/env/env_show.py +0 -0
  64. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/export_puml.py +0 -0
  65. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_add.py +0 -0
  66. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_attach.py +0 -0
  67. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_clone.py +0 -0
  68. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_delete.py +0 -0
  69. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_detach.py +0 -0
  70. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_diff.py +0 -0
  71. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_discard.py +0 -0
  72. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_drift.py +0 -0
  73. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_edit.py +0 -0
  74. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_env.py +0 -0
  75. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_fork.py +0 -0
  76. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_git.py +0 -0
  77. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_hook_add.py +0 -0
  78. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_hook_remove.py +0 -0
  79. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_hooks.py +0 -0
  80. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_inject_config.py +0 -0
  81. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_list.py +0 -0
  82. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_order.py +0 -0
  83. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_outdated.py +0 -0
  84. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_pin.py +0 -0
  85. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_pip_install.py +0 -0
  86. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_pull.py +0 -0
  87. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_remove.py +0 -0
  88. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_rename.py +0 -0
  89. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_search.py +0 -0
  90. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_status.py +0 -0
  91. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_sync_template.py +0 -0
  92. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_test.py +0 -0
  93. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_translate.py +0 -0
  94. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_upgrade.py +0 -0
  95. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature/feature_versions.py +0 -0
  96. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/feature_compile.py +0 -0
  97. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/linter.py +0 -0
  98. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/locust.py +0 -0
  99. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/__init__.py +0 -0
  100. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_clean.py +0 -0
  101. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_commands.py +0 -0
  102. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_complete.py +0 -0
  103. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_config.py +0 -0
  104. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_configure.py +0 -0
  105. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_console.py +0 -0
  106. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_create.py +0 -0
  107. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_derive.py +0 -0
  108. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_down.py +0 -0
  109. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_drift.py +0 -0
  110. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_list.py +0 -0
  111. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_logs.py +0 -0
  112. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_missing.py +0 -0
  113. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_port.py +0 -0
  114. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_release.py +0 -0
  115. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_routes.py +0 -0
  116. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_run.py +0 -0
  117. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_select.py +0 -0
  118. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_shell.py +0 -0
  119. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_signals.py +0 -0
  120. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_status.py +0 -0
  121. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_sync.py +0 -0
  122. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_sync_template.py +0 -0
  123. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_test.py +0 -0
  124. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_up.py +0 -0
  125. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/product/product_validate.py +0 -0
  126. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/release/__init__.py +0 -0
  127. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/release/release_core.py +0 -0
  128. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/selenium.py +0 -0
  129. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/__init__.py +0 -0
  130. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_add_feature.py +0 -0
  131. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_configs.py +0 -0
  132. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_create.py +0 -0
  133. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_deps.py +0 -0
  134. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_features.py +0 -0
  135. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_fetch.py +0 -0
  136. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_fix.py +0 -0
  137. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_info.py +0 -0
  138. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_list.py +0 -0
  139. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/spl/spl_utils.py +0 -0
  140. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/uvl/uvl_utils.py +0 -0
  141. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/commands/version.py +0 -0
  142. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/services/__init__.py +0 -0
  143. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/services/preflight.py +0 -0
  144. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/services/release.py +0 -0
  145. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/__init__.py +0 -0
  146. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/cache_utils.py +0 -0
  147. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/command_loader.py +0 -0
  148. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/contract_freshness.py +0 -0
  149. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/db_utils.py +0 -0
  150. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/decorators.py +0 -0
  151. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/dynamic_imports.py +0 -0
  152. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/feature_installer.py +0 -0
  153. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/feature_utils.py +0 -0
  154. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/git_url.py +0 -0
  155. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/integrity.py +0 -0
  156. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/lifecycle.py +0 -0
  157. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/manifest.py +0 -0
  158. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/path_utils.py +0 -0
  159. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli/utils/template_drift.py +0 -0
  160. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli.egg-info/dependency_links.txt +0 -0
  161. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli.egg-info/entry_points.txt +0 -0
  162. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli.egg-info/requires.txt +0 -0
  163. {splent_cli-1.5.0 → splent_cli-1.5.1}/src/splent_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: splent_cli
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: SPLENT-CLI is a CLI to be able to work on your development more easily.
5
5
  Author-email: DiversoLab <diversolab@us.es>
6
6
  Project-URL: Homepage, https://github.com/diverso-lab/splent_cli
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "splent_cli"
7
- version = "1.5.0"
7
+ version = "1.5.1"
8
8
  description = "SPLENT-CLI is a CLI to be able to work on your development more easily."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -1,13 +1,11 @@
1
1
  import os
2
2
 
3
3
  import click
4
- from flask import current_app
5
- from flask_migrate import migrate as alembic_migrate, upgrade as alembic_upgrade
4
+ from flask_migrate import migrate as alembic_migrate
6
5
 
7
6
  from splent_cli.utils.decorators import requires_db
8
7
  from splent_cli.services import context
9
8
  from splent_cli.utils.lifecycle import (
10
- advance_state,
11
9
  resolve_feature_key_from_entry,
12
10
  require_editable,
13
11
  )
@@ -53,16 +51,17 @@ def _is_empty_migration(path: str) -> bool:
53
51
  short_help="Generate and apply migrations (all features or a single one).",
54
52
  )
55
53
  @click.argument("feature", required=False, default=None)
54
+ @click.option(
55
+ "-m", "message", default=None, help="Migration message (defaults to feature name)."
56
+ )
56
57
  @context.requires_product
57
- def db_migrate(feature):
58
+ def db_migrate(feature, message):
58
59
  """
59
60
  Generate new migration files for features that have schema changes,
60
61
  then apply all pending migrations.
61
62
 
62
63
  Empty migrations (no schema changes detected) are automatically removed.
63
64
  """
64
- app = current_app
65
-
66
65
  if feature:
67
66
  dirs = {}
68
67
  mdir = MigrationManager.get_feature_migration_dir(feature)
@@ -84,7 +83,6 @@ def db_migrate(feature):
84
83
 
85
84
  # Build entry→key lookup for manifest updates
86
85
  product_path = PathUtils.get_app_base_dir()
87
- product_name = os.getenv("SPLENT_APP", "")
88
86
  entry_lookup = {}
89
87
  for entry in get_features_from_pyproject() or []:
90
88
  key, ns, name, version = resolve_feature_key_from_entry(entry)
@@ -110,7 +108,7 @@ def db_migrate(feature):
110
108
  alembic_logger.setLevel(logging.WARNING)
111
109
 
112
110
  try:
113
- alembic_migrate(directory=mdir, message=feat)
111
+ alembic_migrate(directory=mdir, message=message or feat)
114
112
  except Exception as e:
115
113
  if os.getenv("SPLENT_DEBUG"):
116
114
  click.secho(
@@ -142,30 +140,5 @@ def db_migrate(feature):
142
140
  else:
143
141
  click.echo(click.style(f" ✔ {feat}: up to date", fg="green"))
144
142
 
145
- # Apply pending migrations
146
- try:
147
- alembic_upgrade(directory=mdir)
148
- revision = MigrationManager.get_current_feature_revision(
149
- feat, app.extensions["migrate"].db.engine
150
- )
151
- MigrationManager.update_feature_status(app, feat, revision)
152
- click.echo(click.style(f" ✅ {feat} → {revision or 'head'}", fg="green"))
153
-
154
- # Advance lifecycle state to "migrated"
155
- info = entry_lookup.get(feat)
156
- if info:
157
- key, ns, name, version = info
158
- advance_state(
159
- product_path,
160
- product_name,
161
- key,
162
- to="migrated",
163
- namespace=ns,
164
- name=name,
165
- version=version,
166
- )
167
- except Exception as e:
168
- click.echo(click.style(f" ❌ {feat}: {e}", fg="red"))
169
-
170
143
 
171
144
  cli_command = db_migrate
@@ -206,7 +206,28 @@ def db_rollback(feature, steps, cascade):
206
206
  )
207
207
  break
208
208
  except Exception as e:
209
- click.secho(f" {feature}: {e}", fg="red")
209
+ click.secho(f" {feature}: {e}", fg="red")
210
+ raise SystemExit(1)
211
+
212
+ # Offer to delete migration files if fully rolled back to base
213
+ if revision is None:
214
+ versions_dir = os.path.join(mdir, "versions")
215
+ if os.path.isdir(versions_dir):
216
+ migration_files = [
217
+ f
218
+ for f in os.listdir(versions_dir)
219
+ if f.endswith(".py") and not f.startswith("__")
220
+ ]
221
+ if migration_files and click.confirm(
222
+ f" Delete {len(migration_files)} migration file(s)?",
223
+ default=False,
224
+ ):
225
+ for f in migration_files:
226
+ os.remove(os.path.join(versions_dir, f))
227
+ click.echo(
228
+ click.style(" deleted: ", dim=True)
229
+ + f"{len(migration_files)} file(s)"
230
+ )
210
231
 
211
232
 
212
233
  cli_command = db_rollback
@@ -175,6 +175,10 @@ def _print_diff(current: dict, inferred: dict) -> bool:
175
175
  ("signals", "provides.signals"),
176
176
  ("translations", "provides.translations"),
177
177
  ("requires_signals", "requires.signals"),
178
+ ("extensible_services", "extensible.services"),
179
+ ("extensible_templates", "extensible.templates"),
180
+ ("extensible_models", "extensible.models"),
181
+ ("extensible_hooks", "extensible.hooks"),
178
182
  ]
179
183
 
180
184
  diff_lines = []
@@ -88,9 +88,13 @@ def make_feature(full_name):
88
88
  if short_name.startswith("splent_feature_"):
89
89
  short_name = short_name[len("splent_feature_") :]
90
90
 
91
+ # PascalCase for class names: notes_tags → NotesTags
92
+ pascal_name = "".join(w.capitalize() for w in short_name.split("_"))
93
+
91
94
  template_ctx = {
92
95
  "feature_name": feature_name,
93
96
  "short_name": short_name,
97
+ "pascal_name": pascal_name,
94
98
  "org_safe": org_safe,
95
99
  "feature_import": f"{org_safe}.{feature_name}",
96
100
  "cli_version": _CLI_VERSION,