redeploy 0.2.68__tar.gz → 0.2.69__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 (252) hide show
  1. {redeploy-0.2.68 → redeploy-0.2.69}/PKG-INFO +6 -6
  2. {redeploy-0.2.68 → redeploy-0.2.69}/README.md +5 -5
  3. {redeploy-0.2.68 → redeploy-0.2.69}/pyproject.toml +1 -1
  4. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/__init__.py +1 -1
  5. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/blueprint.py +6 -0
  6. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/steps/__init__.py +23 -2
  7. redeploy-0.2.69/redeploy/steps/docker.py +40 -0
  8. redeploy-0.2.69/redeploy/steps/generic.py +87 -0
  9. redeploy-0.2.69/redeploy/steps/hardware.py +22 -0
  10. redeploy-0.2.69/redeploy/steps/k3s.py +58 -0
  11. redeploy-0.2.69/redeploy/steps/podman.py +41 -0
  12. redeploy-0.2.69/redeploy/steps/process.py +32 -0
  13. redeploy-0.2.69/redeploy/steps/scm.py +22 -0
  14. redeploy-0.2.69/redeploy/steps/transfer.py +22 -0
  15. redeploy-0.2.69/redeploy/tests/test_steps_registry.py +109 -0
  16. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/PKG-INFO +6 -6
  17. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/SOURCES.txt +9 -1
  18. redeploy-0.2.68/redeploy/steps/builtins.py +0 -275
  19. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/__init__.py +0 -0
  20. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/checkers/__init__.py +0 -0
  21. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/preflight_schema.py +0 -0
  22. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/spec_analyzer.py +0 -0
  23. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/__init__.py +0 -0
  24. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/exceptions.py +0 -0
  25. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/executor.py +0 -0
  26. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/handlers.py +0 -0
  27. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/progress.py +0 -0
  28. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/rollback.py +0 -0
  29. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/state.py +0 -0
  30. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/state_apply.py +0 -0
  31. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/utils/__init__.py +0 -0
  32. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/utils/run_container_build.py +0 -0
  33. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/audit.py +0 -0
  34. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/__init__.py +0 -0
  35. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/extractor.py +0 -0
  36. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/__init__.py +0 -0
  37. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/docker_compose.py +0 -0
  38. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/migration.py +0 -0
  39. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/__init__.py +0 -0
  40. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/compose.py +0 -0
  41. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/hardware.py +0 -0
  42. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/infra.py +0 -0
  43. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/migration.py +0 -0
  44. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/__init__.py +0 -0
  45. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/__init__.py +0 -0
  46. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/audit.py +0 -0
  47. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/bump_fix.py +0 -0
  48. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/detect.py +0 -0
  49. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/device_map.py +0 -0
  50. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/device_map_renderers.py +0 -0
  51. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/devices.py +0 -0
  52. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/diagnose.py +0 -0
  53. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/diff.py +0 -0
  54. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/exec_.py +0 -0
  55. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/export.py +0 -0
  56. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/hardware.py +0 -0
  57. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/import_.py +0 -0
  58. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/init.py +0 -0
  59. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/inspect.py +0 -0
  60. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/lint.py +0 -0
  61. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/mcp_cmd.py +0 -0
  62. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/patterns.py +0 -0
  63. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/plan_apply.py +0 -0
  64. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/plugin.py +0 -0
  65. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/probe.py +0 -0
  66. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/prompt_cmd.py +0 -0
  67. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/push.py +0 -0
  68. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/state.py +0 -0
  69. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/status.py +0 -0
  70. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/target.py +0 -0
  71. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/__init__.py +0 -0
  72. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/commands.py +0 -0
  73. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/helpers.py +0 -0
  74. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/monorepo.py +0 -0
  75. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/release.py +0 -0
  76. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/scanner.py +0 -0
  77. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/__init__.py +0 -0
  78. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/changelog_config.py +0 -0
  79. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/git_config.py +0 -0
  80. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/workflow.py +0 -0
  81. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/core.py +0 -0
  82. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/display.py +0 -0
  83. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/query.py +0 -0
  84. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli.py +0 -0
  85. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/__init__.py +0 -0
  86. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/applier.py +0 -0
  87. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/loader.py +0 -0
  88. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/data_sync.py +0 -0
  89. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/__init__.py +0 -0
  90. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/builtin/__init__.py +0 -0
  91. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/detector.py +0 -0
  92. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/hardware.py +0 -0
  93. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/hardware_rules.py +0 -0
  94. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/probes.py +0 -0
  95. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/remote.py +0 -0
  96. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/templates.py +0 -0
  97. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/workflow.py +0 -0
  98. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/discovery.py +0 -0
  99. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/__init__.py +0 -0
  100. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/loader.py +0 -0
  101. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/parser.py +0 -0
  102. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/__init__.py +0 -0
  103. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/context.py +0 -0
  104. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/decorators.py +0 -0
  105. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/docker_steps.py +0 -0
  106. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/exceptions.py +0 -0
  107. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/runner.py +0 -0
  108. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/steps.py +0 -0
  109. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/fleet.py +0 -0
  110. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/__init__.py +0 -0
  111. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/config_txt.py +0 -0
  112. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/__init__.py +0 -0
  113. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/hyperpixel.py +0 -0
  114. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/official.py +0 -0
  115. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/waveshare.py +0 -0
  116. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/fixes.py +0 -0
  117. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/__init__.py +0 -0
  118. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/autostart.py +0 -0
  119. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/browsers.py +0 -0
  120. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/compositors.py +0 -0
  121. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/output_profiles.py +0 -0
  122. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/panels.py +0 -0
  123. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/raspi_config.py +0 -0
  124. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/__init__.py +0 -0
  125. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/decider.py +0 -0
  126. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/hint_provider.py +0 -0
  127. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/log_writer.py +0 -0
  128. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/loop_detector.py +0 -0
  129. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/runner.py +0 -0
  130. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal.py +0 -0
  131. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/__init__.py +0 -0
  132. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/base.py +0 -0
  133. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/config_hints.py +0 -0
  134. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/docker_compose.py +0 -0
  135. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/parsers/__init__.py +0 -0
  136. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/parsers/compose.py +0 -0
  137. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/registry.py +0 -0
  138. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/integrations/__init__.py +0 -0
  139. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/integrations/op3_bridge.py +0 -0
  140. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/__init__.py +0 -0
  141. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/compiler.py +0 -0
  142. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/models.py +0 -0
  143. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/parser.py +0 -0
  144. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/mcp_server.py +0 -0
  145. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/__init__.py +0 -0
  146. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/blueprint.py +0 -0
  147. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/devices.py +0 -0
  148. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/enums.py +0 -0
  149. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/hardware.py +0 -0
  150. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/infra.py +0 -0
  151. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/manifest.py +0 -0
  152. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/persisted.py +0 -0
  153. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/pipeline.py +0 -0
  154. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/plan.py +0 -0
  155. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/spec.py +0 -0
  156. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/observe.py +0 -0
  157. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/parse.py +0 -0
  158. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/patterns.py +0 -0
  159. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plan/__init__.py +0 -0
  160. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plan/planner.py +0 -0
  161. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/__init__.py +0 -0
  162. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/__init__.py +0 -0
  163. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/browser_reload.py +0 -0
  164. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/hardware_diagnostic.py +0 -0
  165. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/notify.py +0 -0
  166. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/process_control.py +0 -0
  167. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/systemd_reload.py +0 -0
  168. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/schema.py +0 -0
  169. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/spec_loader.py +0 -0
  170. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/ssh.py +0 -0
  171. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/steps/kiosk.py +0 -0
  172. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/__init__.py +0 -0
  173. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_analyze.py +0 -0
  174. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_audit.py +0 -0
  175. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_cli.py +0 -0
  176. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_data_sync.py +0 -0
  177. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_discovery.py +0 -0
  178. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_dsl.py +0 -0
  179. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_examples.py +0 -0
  180. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_executor.py +0 -0
  181. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_fleet.py +0 -0
  182. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_git_integration.py +0 -0
  183. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_heal.py +0 -0
  184. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_heal_decider.py +0 -0
  185. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_hooks.py +0 -0
  186. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac.py +0 -0
  187. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac_compose_contract.py +0 -0
  188. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac_docker_compose_contract.py +0 -0
  189. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_manifest.py +0 -0
  190. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_markpact_compiler.py +0 -0
  191. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_markpact_parser.py +0 -0
  192. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_models.py +0 -0
  193. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_observe.py +0 -0
  194. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_parse.py +0 -0
  195. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_patterns.py +0 -0
  196. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_planner_edge.py +0 -0
  197. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_plugins.py +0 -0
  198. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_probes.py +0 -0
  199. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_public_api.py +0 -0
  200. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_resume.py +0 -0
  201. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_spec_loader.py +0 -0
  202. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_ssh.py +0 -0
  203. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_templates.py +0 -0
  204. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_verify.py +0 -0
  205. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version.py +0 -0
  206. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_changelog.py +0 -0
  207. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_cli.py +0 -0
  208. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_manifest.py +0 -0
  209. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_sources.py +0 -0
  210. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_workflow.py +0 -0
  211. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/verify.py +0 -0
  212. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/__init__.py +0 -0
  213. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/bump.py +0 -0
  214. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/changelog.py +0 -0
  215. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/commits.py +0 -0
  216. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/diff.py +0 -0
  217. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/git_integration.py +0 -0
  218. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/git_transaction.py +0 -0
  219. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/manifest.py +0 -0
  220. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/__init__.py +0 -0
  221. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/base.py +0 -0
  222. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/json_.py +0 -0
  223. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/plain.py +0 -0
  224. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/regex.py +0 -0
  225. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/toml_.py +0 -0
  226. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/yaml_.py +0 -0
  227. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/transaction.py +0 -0
  228. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version.py +0 -0
  229. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/dependency_links.txt +0 -0
  230. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/entry_points.txt +0 -0
  231. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/requires.txt +0 -0
  232. {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/top_level.txt +0 -0
  233. {redeploy-0.2.68 → redeploy-0.2.69}/setup.cfg +0 -0
  234. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_blueprint_sources.py +0 -0
  235. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_blueprint_sources_compose.py +0 -0
  236. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_cli_query.py +0 -0
  237. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_argocd_flux_plugin.py +0 -0
  238. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_gitops_ci_plugin.py +0 -0
  239. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_helm_kustomize_plugin.py +0 -0
  240. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_config.py +0 -0
  241. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_kiosk.py +0 -0
  242. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_rules.py +0 -0
  243. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_heal_decider.py +0 -0
  244. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_heal_loop_detector.py +0 -0
  245. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac.py +0 -0
  246. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac_config_hints.py +0 -0
  247. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac_plugin_loading.py +0 -0
  248. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_import_plugin_template.py +0 -0
  249. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_parse.py +0 -0
  250. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_prompt_llm.py +0 -0
  251. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_redeploy.py +0 -0
  252. {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_steps_kiosk.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.68
3
+ Version: 0.2.69
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -32,17 +32,17 @@ Requires-Dist: mcp>=1.0; extra == "mcp"
32
32
 
33
33
  ## AI Cost Tracking
34
34
 
35
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
36
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-35.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
35
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
36
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-36.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
37
37
 
38
- - 🤖 **LLM usage:** $7.5000 (89 commits)
39
- - 👤 **Human dev:** ~$3512 (35.1h @ $100/h, 30min dedup)
38
+ - 🤖 **LLM usage:** $7.5000 (90 commits)
39
+ - 👤 **Human dev:** ~$3606 (36.1h @ $100/h, 30min dedup)
40
40
 
41
41
  Generated on 2026-04-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
42
42
 
43
43
  ---
44
44
 
45
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
45
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
46
46
 
47
47
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
48
48
 
@@ -3,17 +3,17 @@
3
3
 
4
4
  ## AI Cost Tracking
5
5
 
6
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-35.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
6
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-36.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
8
 
9
- - 🤖 **LLM usage:** $7.5000 (89 commits)
10
- - 👤 **Human dev:** ~$3512 (35.1h @ $100/h, 30min dedup)
9
+ - 🤖 **LLM usage:** $7.5000 (90 commits)
10
+ - 👤 **Human dev:** ~$3606 (36.1h @ $100/h, 30min dedup)
11
11
 
12
12
  Generated on 2026-04-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
13
13
 
14
14
  ---
15
15
 
16
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
16
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
17
17
 
18
18
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
19
19
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "redeploy"
7
- version = "0.2.68"
7
+ version = "0.2.69"
8
8
  description = "Infrastructure migration toolkit: detect → plan → apply"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -7,7 +7,7 @@ Public API (stable from 0.2.0, semver guaranteed)::
7
7
 
8
8
  Everything not listed in ``__all__`` is internal and may change without notice.
9
9
  """
10
- __version__ = "0.2.68"
10
+ __version__ = "0.2.69"
11
11
 
12
12
  # ── Core models ───────────────────────────────────────────────────────────────
13
13
  from .models import ( # noqa: F401
@@ -212,6 +212,12 @@ def show(blueprint_file, fmt, apply_config, query_expr):
212
212
  from ...models import DeviceBlueprint
213
213
 
214
214
  bp = DeviceBlueprint.load(Path(blueprint_file))
215
+
216
+ # --query: extract specific values with JMESPath
217
+ if query_expr is not None:
218
+ _execute_query_blueprint(bp, query_expr, fmt)
219
+ return
220
+
215
221
  if fmt == "json":
216
222
  import json as _json
217
223
  click.echo(_json.dumps(bp.model_dump(mode="json"), indent=2))
@@ -19,11 +19,32 @@ from typing import Any, Optional
19
19
 
20
20
  from ..models import MigrationStep
21
21
 
22
- from . import builtins, kiosk
22
+ from . import (
23
+ docker,
24
+ generic,
25
+ hardware,
26
+ k3s,
27
+ kiosk,
28
+ podman,
29
+ process,
30
+ scm,
31
+ transfer,
32
+ )
23
33
 
24
34
  # Merge domain modules into a single flat registry.
35
+ _ALL_MODULES = (
36
+ docker.ALL
37
+ + generic.ALL
38
+ + hardware.ALL
39
+ + k3s.ALL
40
+ + kiosk.ALL
41
+ + podman.ALL
42
+ + process.ALL
43
+ + scm.ALL
44
+ + transfer.ALL
45
+ )
25
46
  _LIBRARY: dict[str, MigrationStep] = {
26
- s.id: s for s in (builtins.ALL + kiosk.ALL)
47
+ s.id: s for s in _ALL_MODULES
27
48
  }
28
49
 
29
50
 
@@ -0,0 +1,40 @@
1
+ """Docker container runtime domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ DOCKER_PRUNE = _step(
12
+ id="docker_prune",
13
+ action=StepAction.SSH_CMD,
14
+ description="Prune unused Docker images and build cache",
15
+ command="docker image prune -f && docker builder prune -f",
16
+ risk=ConflictSeverity.LOW,
17
+ )
18
+
19
+ DOCKER_COMPOSE_DOWN = _step(
20
+ id="docker_compose_down",
21
+ action=StepAction.DOCKER_COMPOSE_DOWN,
22
+ description="Stop Docker Compose stack",
23
+ command="docker compose down",
24
+ risk=ConflictSeverity.MEDIUM,
25
+ rollback_command="docker compose up -d",
26
+ )
27
+
28
+ RESTART_TRAEFIK = _step(
29
+ id="restart_traefik",
30
+ action=StepAction.SSH_CMD,
31
+ description="Restart Traefik container",
32
+ command="docker restart $(docker ps -q --filter name=traefik) 2>/dev/null || true",
33
+ risk=ConflictSeverity.LOW,
34
+ )
35
+
36
+ ALL: list[MigrationStep] = [
37
+ DOCKER_PRUNE,
38
+ DOCKER_COMPOSE_DOWN,
39
+ RESTART_TRAEFIK,
40
+ ]
@@ -0,0 +1,87 @@
1
+ """Generic / cross-domain utility steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ # ── waits ─────────────────────────────────────────────────────────────────────
12
+
13
+ WAIT_30 = _step(
14
+ id="wait_startup",
15
+ action=StepAction.WAIT,
16
+ description="Wait 30 s for services to start",
17
+ seconds=30,
18
+ risk=ConflictSeverity.LOW,
19
+ )
20
+
21
+ WAIT_60 = _step(
22
+ id="wait_startup_long",
23
+ action=StepAction.WAIT,
24
+ description="Wait 60 s for services to start (slow build)",
25
+ seconds=60,
26
+ risk=ConflictSeverity.LOW,
27
+ )
28
+
29
+ # ── verify ────────────────────────────────────────────────────────────────────
30
+
31
+ HTTP_HEALTH_CHECK = _step(
32
+ id="http_health_check",
33
+ action=StepAction.HTTP_CHECK,
34
+ description="Verify backend health endpoint",
35
+ url=None, # must be set by caller
36
+ expect="healthy",
37
+ risk=ConflictSeverity.LOW,
38
+ )
39
+
40
+ VERSION_CHECK = _step(
41
+ id="version_check",
42
+ action=StepAction.VERSION_CHECK,
43
+ description="Verify deployed version",
44
+ url=None, # must be set by caller
45
+ expect=None,
46
+ risk=ConflictSeverity.LOW,
47
+ )
48
+
49
+ # ── systemd generic ───────────────────────────────────────────────────────────
50
+
51
+ SYSTEMCTL_RESTART = _step(
52
+ id="systemctl_restart",
53
+ action=StepAction.SYSTEMCTL_START,
54
+ description="Restart a systemd service (set command= to override)",
55
+ command="systemctl restart {service}",
56
+ risk=ConflictSeverity.LOW,
57
+ )
58
+
59
+ SYSTEMCTL_DAEMON_RELOAD = _step(
60
+ id="systemctl_daemon_reload",
61
+ action=StepAction.SSH_CMD,
62
+ description="Reload systemd daemon",
63
+ command="systemctl daemon-reload",
64
+ risk=ConflictSeverity.LOW,
65
+ )
66
+
67
+ # ── nginx ─────────────────────────────────────────────────────────────────────
68
+
69
+ STOP_NGINX = _step(
70
+ id="stop_nginx",
71
+ action=StepAction.SYSTEMCTL_STOP,
72
+ service="nginx",
73
+ description="Stop host nginx (conflicts on port 80)",
74
+ command="systemctl stop nginx && systemctl disable nginx",
75
+ risk=ConflictSeverity.MEDIUM,
76
+ rollback_command="systemctl start nginx",
77
+ )
78
+
79
+ ALL: list[MigrationStep] = [
80
+ WAIT_30,
81
+ WAIT_60,
82
+ HTTP_HEALTH_CHECK,
83
+ VERSION_CHECK,
84
+ SYSTEMCTL_RESTART,
85
+ SYSTEMCTL_DAEMON_RELOAD,
86
+ STOP_NGINX,
87
+ ]
@@ -0,0 +1,22 @@
1
+ """Hardware diagnostic domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ HARDWARE_DIAGNOSTIC = _step(
12
+ id="hardware_diagnostic",
13
+ action=StepAction.PLUGIN,
14
+ plugin_type="hardware_diagnostic",
15
+ description="Analyze system hardware and provide configuration recommendations",
16
+ plugin_params={"checks": ["platform", "cpu", "memory", "storage"], "platform": "auto", "verbose": True},
17
+ risk=ConflictSeverity.LOW,
18
+ )
19
+
20
+ ALL: list[MigrationStep] = [
21
+ HARDWARE_DIAGNOSTIC,
22
+ ]
@@ -0,0 +1,58 @@
1
+ """k3s / Kubernetes domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ FLUSH_K3S_IPTABLES = _step(
12
+ id="flush_k3s_iptables",
13
+ action=StepAction.SSH_CMD,
14
+ description="Flush k3s CNI-HOSTPORT-DNAT + KUBE-* chains (stale rules block Docker-proxy on 80/443)",
15
+ command=(
16
+ "iptables -t nat -F CNI-HOSTPORT-DNAT 2>/dev/null || true && "
17
+ "iptables -t nat -F CNI-HOSTPORT-MASQ 2>/dev/null || true && "
18
+ "iptables -t nat -F KUBE-SERVICES 2>/dev/null || true && "
19
+ "iptables -t nat -F KUBE-NODEPORTS 2>/dev/null || true && "
20
+ "iptables -t filter -F KUBE-FORWARD 2>/dev/null || true && "
21
+ "echo iptables-flushed"
22
+ ),
23
+ risk=ConflictSeverity.LOW,
24
+ )
25
+
26
+ DELETE_K3S_INGRESSES = _step(
27
+ id="delete_k3s_ingresses",
28
+ action=StepAction.KUBECTL_DELETE,
29
+ description="Delete k3s ingresses to remove iptables DNAT rules",
30
+ command="k3s kubectl delete ingress --all-namespaces --all 2>/dev/null || true",
31
+ risk=ConflictSeverity.LOW,
32
+ )
33
+
34
+ STOP_K3S = _step(
35
+ id="stop_k3s",
36
+ action=StepAction.SYSTEMCTL_STOP,
37
+ service="k3s",
38
+ description="Stop k3s to free ports 80/443",
39
+ command="systemctl stop k3s",
40
+ risk=ConflictSeverity.MEDIUM,
41
+ rollback_command="systemctl start k3s",
42
+ )
43
+
44
+ DISABLE_K3S = _step(
45
+ id="disable_k3s",
46
+ action=StepAction.SYSTEMCTL_DISABLE,
47
+ service="k3s",
48
+ description="Disable k3s on boot",
49
+ command="systemctl disable k3s",
50
+ risk=ConflictSeverity.LOW,
51
+ )
52
+
53
+ ALL: list[MigrationStep] = [
54
+ FLUSH_K3S_IPTABLES,
55
+ DELETE_K3S_INGRESSES,
56
+ STOP_K3S,
57
+ DISABLE_K3S,
58
+ ]
@@ -0,0 +1,41 @@
1
+ """Podman / Quadlet domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ PODMAN_DAEMON_RELOAD = _step(
12
+ id="podman_daemon_reload",
13
+ action=StepAction.SYSTEMCTL_START,
14
+ description="Reload systemd to pick up Quadlet unit files",
15
+ command="systemctl --user daemon-reload",
16
+ risk=ConflictSeverity.LOW,
17
+ )
18
+
19
+ STOP_PODMAN = _step(
20
+ id="stop_podman",
21
+ action=StepAction.SYSTEMCTL_STOP,
22
+ service="podman",
23
+ description="Stop all Podman containers via systemd",
24
+ command="systemctl stop podman.service 2>/dev/null || podman stop --all 2>/dev/null || true",
25
+ risk=ConflictSeverity.MEDIUM,
26
+ rollback_command="systemctl start podman.service 2>/dev/null || true",
27
+ )
28
+
29
+ ENABLE_PODMAN_UNIT = _step(
30
+ id="enable_podman_unit",
31
+ action=StepAction.SYSTEMCTL_START,
32
+ description="Enable and start a Podman Quadlet unit (set service= to override)",
33
+ command="systemctl daemon-reload && systemctl enable --now {service}.service",
34
+ risk=ConflictSeverity.LOW,
35
+ )
36
+
37
+ ALL: list[MigrationStep] = [
38
+ PODMAN_DAEMON_RELOAD,
39
+ STOP_PODMAN,
40
+ ENABLE_PODMAN_UNIT,
41
+ ]
@@ -0,0 +1,32 @@
1
+ """Process-control domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ KILL_PROCESSES_ON_PORTS = _step(
12
+ id="kill_processes_on_ports",
13
+ action=StepAction.PLUGIN,
14
+ plugin_type="process_control",
15
+ description="Kill processes on specified ports (auto-detects PIDs)",
16
+ plugin_params={"ports": [], "strategy": "graceful", "timeout": 10, "notify": True},
17
+ risk=ConflictSeverity.LOW,
18
+ )
19
+
20
+ KILL_DEV_PROCESSES = _step(
21
+ id="kill_dev_processes",
22
+ action=StepAction.PLUGIN,
23
+ plugin_type="process_control",
24
+ description="Kill common dev server processes (vite, uvicorn, python)",
25
+ plugin_params={"ports": [8100, 8101, 8202, 3000, 5173], "strategy": "graceful", "timeout": 5, "notify": True},
26
+ risk=ConflictSeverity.LOW,
27
+ )
28
+
29
+ ALL: list[MigrationStep] = [
30
+ KILL_PROCESSES_ON_PORTS,
31
+ KILL_DEV_PROCESSES,
32
+ ]
@@ -0,0 +1,22 @@
1
+ """Source-control management domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ GIT_PULL = _step(
12
+ id="git_pull",
13
+ action=StepAction.SSH_CMD,
14
+ description="Pull latest code from git (cd to remote_dir first)",
15
+ command="git -C ~/app pull --ff-only",
16
+ risk=ConflictSeverity.LOW,
17
+ rollback_command="git -C ~/app reset --hard HEAD@{1}",
18
+ )
19
+
20
+ ALL: list[MigrationStep] = [
21
+ GIT_PULL,
22
+ ]
@@ -0,0 +1,22 @@
1
+ """File-transfer domain steps."""
2
+ from __future__ import annotations
3
+
4
+ from ..models import ConflictSeverity, MigrationStep, StepAction
5
+
6
+
7
+ def _step(id: str, action: StepAction, description: str, **kw) -> MigrationStep:
8
+ return MigrationStep(id=id, action=action, description=description, **kw)
9
+
10
+
11
+ SYNC_ENV = _step(
12
+ id="sync_env",
13
+ action=StepAction.SCP,
14
+ description="Copy .env file to remote",
15
+ src=None, # caller sets src/dst
16
+ dst=None,
17
+ risk=ConflictSeverity.LOW,
18
+ )
19
+
20
+ ALL: list[MigrationStep] = [
21
+ SYNC_ENV,
22
+ ]
@@ -0,0 +1,109 @@
1
+ """Tests that every domain module in redeploy.steps is correctly wired into StepLibrary."""
2
+ from __future__ import annotations
3
+
4
+ import pytest
5
+
6
+ from redeploy.models import MigrationStep
7
+ from redeploy.steps import StepLibrary
8
+ from redeploy.steps import (
9
+ docker,
10
+ generic,
11
+ hardware,
12
+ k3s,
13
+ kiosk,
14
+ podman,
15
+ process,
16
+ scm,
17
+ transfer,
18
+ )
19
+
20
+
21
+ ALL_MODULES = [
22
+ docker,
23
+ generic,
24
+ hardware,
25
+ k3s,
26
+ kiosk,
27
+ podman,
28
+ process,
29
+ scm,
30
+ transfer,
31
+ ]
32
+
33
+
34
+ class TestNoDuplicateIds:
35
+ def test_no_duplicate_ids_within_each_module(self):
36
+ for mod in ALL_MODULES:
37
+ ids = [s.id for s in mod.ALL]
38
+ assert len(ids) == len(set(ids)), f"duplicate ids in {mod.__name__}: {ids}"
39
+
40
+ def test_no_duplicate_ids_across_all_modules(self):
41
+ all_ids = []
42
+ for mod in ALL_MODULES:
43
+ all_ids.extend(s.id for s in mod.ALL)
44
+ assert len(all_ids) == len(set(all_ids)), f"duplicate ids across modules: {all_ids}"
45
+
46
+
47
+ class TestAllStepsReachableViaLibrary:
48
+ @pytest.mark.parametrize(
49
+ "module",
50
+ ALL_MODULES,
51
+ ids=lambda m: m.__name__.split(".")[-1],
52
+ )
53
+ def test_every_step_in_library(self, module):
54
+ for step in module.ALL:
55
+ found = StepLibrary.get(step.id)
56
+ assert found is not None, f"{step.id} missing from StepLibrary"
57
+ assert isinstance(found, MigrationStep)
58
+
59
+
60
+ class TestLibraryGetReturnsCopy:
61
+ def test_mutating_copy_does_not_affect_template(self):
62
+ s1 = StepLibrary.get("http_health_check")
63
+ s2 = StepLibrary.get("http_health_check")
64
+ assert s1 is not s2
65
+ s1.url = "https://modified.example.com"
66
+ assert s2.url != s1.url
67
+
68
+
69
+ class TestKnownStepsExist:
70
+ def test_k3s_steps(self):
71
+ for sid in ("flush_k3s_iptables", "delete_k3s_ingresses", "stop_k3s", "disable_k3s"):
72
+ assert StepLibrary.get(sid) is not None
73
+
74
+ def test_docker_steps(self):
75
+ for sid in ("docker_prune", "docker_compose_down", "restart_traefik"):
76
+ assert StepLibrary.get(sid) is not None
77
+
78
+ def test_podman_steps(self):
79
+ for sid in ("podman_daemon_reload", "stop_podman", "enable_podman_unit"):
80
+ assert StepLibrary.get(sid) is not None
81
+
82
+ def test_generic_steps(self):
83
+ for sid in (
84
+ "wait_startup",
85
+ "wait_startup_long",
86
+ "http_health_check",
87
+ "version_check",
88
+ "systemctl_restart",
89
+ "systemctl_daemon_reload",
90
+ "stop_nginx",
91
+ ):
92
+ assert StepLibrary.get(sid) is not None
93
+
94
+ def test_scm_steps(self):
95
+ assert StepLibrary.get("git_pull") is not None
96
+
97
+ def test_transfer_steps(self):
98
+ assert StepLibrary.get("sync_env") is not None
99
+
100
+ def test_process_steps(self):
101
+ for sid in ("kill_processes_on_ports", "kill_dev_processes"):
102
+ assert StepLibrary.get(sid) is not None
103
+
104
+ def test_hardware_steps(self):
105
+ assert StepLibrary.get("hardware_diagnostic") is not None
106
+
107
+ def test_kiosk_steps(self):
108
+ for sid in ("kanshi_dsi_only", "autostart_kiosk", "browser_kiosk_script"):
109
+ assert StepLibrary.get(sid) is not None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.68
3
+ Version: 0.2.69
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -32,17 +32,17 @@ Requires-Dist: mcp>=1.0; extra == "mcp"
32
32
 
33
33
  ## AI Cost Tracking
34
34
 
35
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
36
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-35.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
35
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
36
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-36.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
37
37
 
38
- - 🤖 **LLM usage:** $7.5000 (89 commits)
39
- - 👤 **Human dev:** ~$3512 (35.1h @ $100/h, 30min dedup)
38
+ - 🤖 **LLM usage:** $7.5000 (90 commits)
39
+ - 👤 **Human dev:** ~$3606 (36.1h @ $100/h, 30min dedup)
40
40
 
41
41
  Generated on 2026-04-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
42
42
 
43
43
  ---
44
44
 
45
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.68-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
45
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.69-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
46
46
 
47
47
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
48
48
 
@@ -163,8 +163,15 @@ redeploy/plugins/builtin/notify.py
163
163
  redeploy/plugins/builtin/process_control.py
164
164
  redeploy/plugins/builtin/systemd_reload.py
165
165
  redeploy/steps/__init__.py
166
- redeploy/steps/builtins.py
166
+ redeploy/steps/docker.py
167
+ redeploy/steps/generic.py
168
+ redeploy/steps/hardware.py
169
+ redeploy/steps/k3s.py
167
170
  redeploy/steps/kiosk.py
171
+ redeploy/steps/podman.py
172
+ redeploy/steps/process.py
173
+ redeploy/steps/scm.py
174
+ redeploy/steps/transfer.py
168
175
  redeploy/tests/__init__.py
169
176
  redeploy/tests/test_analyze.py
170
177
  redeploy/tests/test_audit.py
@@ -196,6 +203,7 @@ redeploy/tests/test_public_api.py
196
203
  redeploy/tests/test_resume.py
197
204
  redeploy/tests/test_spec_loader.py
198
205
  redeploy/tests/test_ssh.py
206
+ redeploy/tests/test_steps_registry.py
199
207
  redeploy/tests/test_templates.py
200
208
  redeploy/tests/test_verify.py
201
209
  redeploy/tests/test_version.py