redeploy 0.2.11__tar.gz → 0.2.13__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 (109) hide show
  1. {redeploy-0.2.11 → redeploy-0.2.13}/PKG-INFO +6 -6
  2. {redeploy-0.2.11 → redeploy-0.2.13}/README.md +5 -5
  3. {redeploy-0.2.11 → redeploy-0.2.13}/pyproject.toml +1 -1
  4. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/__init__.py +1 -1
  5. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_examples.py +29 -1
  6. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/PKG-INFO +6 -6
  7. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/apply/__init__.py +0 -0
  8. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/apply/executor.py +0 -0
  9. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/cli.py +0 -0
  10. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/data_sync.py +0 -0
  11. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/__init__.py +0 -0
  12. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/detector.py +0 -0
  13. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/probes.py +0 -0
  14. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/remote.py +0 -0
  15. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/templates.py +0 -0
  16. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/detect/workflow.py +0 -0
  17. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/discovery.py +0 -0
  18. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl/__init__.py +0 -0
  19. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl/loader.py +0 -0
  20. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl/parser.py +0 -0
  21. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/__init__.py +0 -0
  22. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/context.py +0 -0
  23. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/decorators.py +0 -0
  24. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/docker_steps.py +0 -0
  25. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/exceptions.py +0 -0
  26. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/runner.py +0 -0
  27. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/dsl_python/steps.py +0 -0
  28. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/fleet.py +0 -0
  29. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/__init__.py +0 -0
  30. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/base.py +0 -0
  31. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/docker_compose.py +0 -0
  32. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/parsers/__init__.py +0 -0
  33. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/parsers/compose.py +0 -0
  34. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/iac/registry.py +0 -0
  35. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/markpact/__init__.py +0 -0
  36. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/markpact/compiler.py +0 -0
  37. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/markpact/models.py +0 -0
  38. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/markpact/parser.py +0 -0
  39. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/models.py +0 -0
  40. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/observe.py +0 -0
  41. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/parse.py +0 -0
  42. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/patterns.py +0 -0
  43. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plan/__init__.py +0 -0
  44. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plan/planner.py +0 -0
  45. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plugins/__init__.py +0 -0
  46. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plugins/builtin/__init__.py +0 -0
  47. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plugins/builtin/browser_reload.py +0 -0
  48. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plugins/builtin/notify.py +0 -0
  49. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/plugins/builtin/systemd_reload.py +0 -0
  50. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/spec_loader.py +0 -0
  51. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/ssh.py +0 -0
  52. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/steps.py +0 -0
  53. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/__init__.py +0 -0
  54. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_cli.py +0 -0
  55. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_data_sync.py +0 -0
  56. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_discovery.py +0 -0
  57. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_dsl.py +0 -0
  58. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_executor.py +0 -0
  59. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_fleet.py +0 -0
  60. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_git_integration.py +0 -0
  61. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_iac.py +0 -0
  62. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_manifest.py +0 -0
  63. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_markpact_compiler.py +0 -0
  64. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_markpact_parser.py +0 -0
  65. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_models.py +0 -0
  66. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_observe.py +0 -0
  67. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_parse.py +0 -0
  68. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_patterns.py +0 -0
  69. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_planner_edge.py +0 -0
  70. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_plugins.py +0 -0
  71. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_probes.py +0 -0
  72. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_public_api.py +0 -0
  73. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_spec_loader.py +0 -0
  74. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_ssh.py +0 -0
  75. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_templates.py +0 -0
  76. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_verify.py +0 -0
  77. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_version.py +0 -0
  78. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_version_changelog.py +0 -0
  79. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_version_cli.py +0 -0
  80. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_version_manifest.py +0 -0
  81. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_version_sources.py +0 -0
  82. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/tests/test_workflow.py +0 -0
  83. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/verify.py +0 -0
  84. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/__init__.py +0 -0
  85. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/bump.py +0 -0
  86. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/changelog.py +0 -0
  87. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/commits.py +0 -0
  88. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/diff.py +0 -0
  89. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/git_integration.py +0 -0
  90. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/git_transaction.py +0 -0
  91. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/manifest.py +0 -0
  92. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/__init__.py +0 -0
  93. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/base.py +0 -0
  94. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/json_.py +0 -0
  95. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/plain.py +0 -0
  96. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/regex.py +0 -0
  97. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/toml_.py +0 -0
  98. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/sources/yaml_.py +0 -0
  99. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version/transaction.py +0 -0
  100. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy/version.py +0 -0
  101. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/SOURCES.txt +0 -0
  102. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/dependency_links.txt +0 -0
  103. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/entry_points.txt +0 -0
  104. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/requires.txt +0 -0
  105. {redeploy-0.2.11 → redeploy-0.2.13}/redeploy.egg-info/top_level.txt +0 -0
  106. {redeploy-0.2.11 → redeploy-0.2.13}/setup.cfg +0 -0
  107. {redeploy-0.2.11 → redeploy-0.2.13}/tests/test_iac.py +0 -0
  108. {redeploy-0.2.11 → redeploy-0.2.13}/tests/test_parse.py +0 -0
  109. {redeploy-0.2.11 → redeploy-0.2.13}/tests/test_redeploy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.11
3
+ Version: 0.2.13
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -27,17 +27,17 @@ Requires-Dist: pfix>=0.1.60; extra == "dev"
27
27
 
28
28
  ## AI Cost Tracking
29
29
 
30
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.11-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
31
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
30
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.13-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
31
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.80-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
32
32
 
33
- - 🤖 **LLM usage:** $4.5000 (30 commits)
34
- - 👤 **Human dev:** ~$898 (9.0h @ $100/h, 30min dedup)
33
+ - 🤖 **LLM usage:** $4.8000 (32 commits)
34
+ - 👤 **Human dev:** ~$925 (9.3h @ $100/h, 30min dedup)
35
35
 
36
36
  Generated on 2026-04-20 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
37
37
 
38
38
  ---
39
39
 
40
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.11-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
40
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.13-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
41
41
 
42
42
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
43
43
 
@@ -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.11-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-$4.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.0h-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.13-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-$4.80-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
8
 
9
- - 🤖 **LLM usage:** $4.5000 (30 commits)
10
- - 👤 **Human dev:** ~$898 (9.0h @ $100/h, 30min dedup)
9
+ - 🤖 **LLM usage:** $4.8000 (32 commits)
10
+ - 👤 **Human dev:** ~$925 (9.3h @ $100/h, 30min dedup)
11
11
 
12
12
  Generated on 2026-04-20 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.11-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.13-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.11"
7
+ version = "0.2.13"
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.11"
10
+ __version__ = "0.2.13"
11
11
 
12
12
  # ── Core models ───────────────────────────────────────────────────────────────
13
13
  from .models import ( # noqa: F401
@@ -13,6 +13,7 @@ import yaml
13
13
  from redeploy.fleet import FleetConfig, Stage, DeviceExpectation
14
14
  from redeploy.models import MigrationSpec, DeployStrategy, StepAction
15
15
  from redeploy.plan.planner import Planner
16
+ from redeploy.spec_loader import load_migration_spec
16
17
  from redeploy.steps import StepLibrary
17
18
 
18
19
  EXAMPLES_DIR = Path(__file__).resolve().parents[2] / "examples"
@@ -23,13 +24,18 @@ MIGRATION_YAMLS = sorted(EXAMPLES_DIR.glob("yaml/*/migration.yaml"))
23
24
  MULTIENV_YAMLS = sorted(EXAMPLES_DIR.glob("yaml/10-multienv/*.yaml"))
24
25
  FLEET_YAMLS = sorted(EXAMPLES_DIR.glob("yaml/*/fleet.yaml"))
25
26
  REDEPLOY_YAMLS = sorted(EXAMPLES_DIR.glob("yaml/*/redeploy.yaml"))
27
+ SUPPORTED_MARKDOWN_MIGRATIONS = [
28
+ EXAMPLES_DIR / "md" / "01-vps-version-bump" / "migration.md",
29
+ EXAMPLES_DIR / "md" / "02-k3s-to-docker" / "migration.md",
30
+ EXAMPLES_DIR / "md" / "03-docker-to-podman-quadlet" / "migration.md",
31
+ ]
26
32
 
27
33
 
28
34
  # ── helpers ───────────────────────────────────────────────────────────────────
29
35
 
30
36
 
31
37
  def _load_spec(path: Path) -> MigrationSpec:
32
- return MigrationSpec.from_file(path)
38
+ return load_migration_spec(path)
33
39
 
34
40
 
35
41
  def _plan_from_spec(spec: MigrationSpec):
@@ -85,6 +91,28 @@ class TestMigrationYaml:
85
91
  assert rdeploy.exists(), f"Missing redeploy.yaml in {yaml_path.parent.name}"
86
92
 
87
93
 
94
+ @pytest.mark.parametrize("md_path", SUPPORTED_MARKDOWN_MIGRATIONS, ids=lambda p: p.parent.name)
95
+ class TestSupportedMarkdownMigration:
96
+ def test_parses_without_error(self, md_path):
97
+ spec = _load_spec(md_path)
98
+ assert spec.name
99
+
100
+ def test_plan_generates_steps(self, md_path):
101
+ spec = _load_spec(md_path)
102
+ plan = _plan_from_spec(spec)
103
+ assert len(plan.steps) > 0, f"{md_path.parent.name}: plan has 0 steps"
104
+
105
+ def test_has_readme(self, md_path):
106
+ readme = md_path.parent / "README.md"
107
+ assert readme.exists(), f"Missing README.md in {md_path.parent.name}"
108
+
109
+ def test_readme_has_run_section(self, md_path):
110
+ readme = md_path.parent / "README.md"
111
+ content = readme.read_text()
112
+ assert "## Run" in content or "## run" in content.lower(), \
113
+ f"{md_path.parent.name}/README.md missing ## Run section"
114
+
115
+
88
116
  # ── redeploy.yaml manifest tests ──────────────────────────────────────────────
89
117
 
90
118
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redeploy
3
- Version: 0.2.11
3
+ Version: 0.2.13
4
4
  Summary: Infrastructure migration toolkit: detect → plan → apply
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -27,17 +27,17 @@ Requires-Dist: pfix>=0.1.60; extra == "dev"
27
27
 
28
28
  ## AI Cost Tracking
29
29
 
30
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.11-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
31
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
30
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.2.13-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
31
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.80-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-9.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
32
32
 
33
- - 🤖 **LLM usage:** $4.5000 (30 commits)
34
- - 👤 **Human dev:** ~$898 (9.0h @ $100/h, 30min dedup)
33
+ - 🤖 **LLM usage:** $4.8000 (32 commits)
34
+ - 👤 **Human dev:** ~$925 (9.3h @ $100/h, 30min dedup)
35
35
 
36
36
  Generated on 2026-04-20 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
37
37
 
38
38
  ---
39
39
 
40
- ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.11-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
40
+ ![PyPI](https://img.shields.io/badge/pypi-redeploy-blue) ![Version](https://img.shields.io/badge/version-0.2.13-blue) ![Python](https://img.shields.io/badge/python-3.10+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
41
41
 
42
42
  Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
43
43
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes