redeploy 0.2.18__tar.gz → 0.2.19__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.
- {redeploy-0.2.18 → redeploy-0.2.19}/PKG-INFO +6 -6
- {redeploy-0.2.18 → redeploy-0.2.19}/README.md +5 -5
- {redeploy-0.2.18 → redeploy-0.2.19}/pyproject.toml +1 -1
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/__init__.py +1 -1
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/apply/executor.py +49 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/cli.py +565 -413
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/models.py +1 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/PKG-INFO +6 -6
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/apply/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/apply/state.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/audit.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/data_sync.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/detector.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/probes.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/remote.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/templates.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/detect/workflow.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/discovery.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl/loader.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl/parser.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/context.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/decorators.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/docker_steps.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/exceptions.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/runner.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/dsl_python/steps.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/fleet.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/base.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/docker_compose.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/parsers/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/parsers/compose.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/iac/registry.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/markpact/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/markpact/compiler.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/markpact/models.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/markpact/parser.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/observe.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/parse.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/patterns.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plan/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plan/planner.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plugins/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plugins/builtin/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plugins/builtin/browser_reload.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plugins/builtin/notify.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/plugins/builtin/systemd_reload.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/spec_loader.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/ssh.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/steps.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_audit.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_cli.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_data_sync.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_discovery.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_dsl.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_examples.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_executor.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_fleet.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_git_integration.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_iac.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_manifest.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_markpact_compiler.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_markpact_parser.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_models.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_observe.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_parse.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_patterns.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_planner_edge.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_plugins.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_probes.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_public_api.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_resume.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_spec_loader.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_ssh.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_templates.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_verify.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_version.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_version_changelog.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_version_cli.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_version_manifest.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_version_sources.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/tests/test_workflow.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/verify.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/bump.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/changelog.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/commits.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/diff.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/git_integration.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/git_transaction.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/manifest.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/__init__.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/base.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/json_.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/plain.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/regex.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/toml_.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/sources/yaml_.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version/transaction.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy/version.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/SOURCES.txt +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/dependency_links.txt +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/entry_points.txt +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/requires.txt +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/redeploy.egg-info/top_level.txt +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/setup.cfg +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/tests/test_iac.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/tests/test_parse.py +0 -0
- {redeploy-0.2.18 → redeploy-0.2.19}/tests/test_redeploy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redeploy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
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
|
-
    
|
|
31
|
+
  
|
|
32
32
|
|
|
33
|
-
- 🤖 **LLM usage:** $5.
|
|
34
|
-
- 👤 **Human dev:** ~$
|
|
33
|
+
- 🤖 **LLM usage:** $5.7000 (38 commits)
|
|
34
|
+
- 👤 **Human dev:** ~$1297 (13.0h @ $100/h, 30min dedup)
|
|
35
35
|
|
|
36
36
|
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
-
    
|
|
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
|
-
    
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $5.
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $5.7000 (38 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$1297 (13.0h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
12
|
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
    
|
|
17
17
|
|
|
18
18
|
Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
|
|
19
19
|
|
|
@@ -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.
|
|
10
|
+
__version__ = "0.2.19"
|
|
11
11
|
|
|
12
12
|
# ── Core models ───────────────────────────────────────────────────────────────
|
|
13
13
|
from .models import ( # noqa: F401
|
|
@@ -296,6 +296,7 @@ class Executor:
|
|
|
296
296
|
StepAction.DOCKER_BUILD: self._run_docker_build,
|
|
297
297
|
StepAction.DOCKER_HEALTH_WAIT: self._run_docker_health_wait,
|
|
298
298
|
StepAction.CONTAINER_LOG_TAIL: self._run_container_log_tail,
|
|
299
|
+
StepAction.PODMAN_BUILD: self._run_podman_build,
|
|
299
300
|
StepAction.SSH_CMD: self._run_ssh,
|
|
300
301
|
StepAction.SCP: self._run_scp,
|
|
301
302
|
StepAction.RSYNC: self._run_rsync,
|
|
@@ -403,6 +404,54 @@ class Executor:
|
|
|
403
404
|
logger.debug(f" build completed in {elapsed + poll_interval}s")
|
|
404
405
|
step.status = StepStatus.DONE
|
|
405
406
|
|
|
407
|
+
def _run_podman_build(self, step: MigrationStep) -> None:
|
|
408
|
+
"""Run podman build on remote with periodic progress polling."""
|
|
409
|
+
cmd = step.command
|
|
410
|
+
if not cmd:
|
|
411
|
+
raise StepError(step, "No command specified")
|
|
412
|
+
|
|
413
|
+
timeout = step.timeout or 1800 # 30 min default for ARM64 builds
|
|
414
|
+
poll_interval = 15 # seconds between progress snapshots
|
|
415
|
+
done_event = threading.Event()
|
|
416
|
+
result_holder: list = []
|
|
417
|
+
|
|
418
|
+
def _ssh_build() -> None:
|
|
419
|
+
r = self.probe.run(cmd, timeout=timeout)
|
|
420
|
+
result_holder.append(r)
|
|
421
|
+
done_event.set()
|
|
422
|
+
|
|
423
|
+
thread = threading.Thread(target=_ssh_build, daemon=True)
|
|
424
|
+
thread.start()
|
|
425
|
+
|
|
426
|
+
elapsed = 0
|
|
427
|
+
while not done_event.wait(timeout=poll_interval):
|
|
428
|
+
elapsed += poll_interval
|
|
429
|
+
snap = self.probe.run(
|
|
430
|
+
"podman system df 2>/dev/null | grep -E 'Image|Cache' | "
|
|
431
|
+
"awk '{print $1, $3, $4}'",
|
|
432
|
+
timeout=10,
|
|
433
|
+
)
|
|
434
|
+
if snap.ok and snap.out.strip():
|
|
435
|
+
lines = " | ".join(snap.out.strip().splitlines())
|
|
436
|
+
msg = f"[{elapsed}s] podman cache: {lines}"
|
|
437
|
+
logger.debug(f" {msg}")
|
|
438
|
+
if self._emitter:
|
|
439
|
+
self._emitter.progress(step.id, msg)
|
|
440
|
+
else:
|
|
441
|
+
msg = f"[{elapsed}s] podman build in progress..."
|
|
442
|
+
logger.debug(f" {msg}")
|
|
443
|
+
if self._emitter:
|
|
444
|
+
self._emitter.progress(step.id, msg)
|
|
445
|
+
|
|
446
|
+
if not result_holder:
|
|
447
|
+
raise StepError(step, "Podman build thread did not return a result")
|
|
448
|
+
r = result_holder[0]
|
|
449
|
+
step.result = r.out[:500]
|
|
450
|
+
if not r.ok:
|
|
451
|
+
raise StepError(step, f"exit={r.exit_code}: {r.stderr[:300]}")
|
|
452
|
+
logger.debug(f" podman build completed in {elapsed + poll_interval}s")
|
|
453
|
+
step.status = StepStatus.DONE
|
|
454
|
+
|
|
406
455
|
def _run_docker_health_wait(self, step: MigrationStep) -> None:
|
|
407
456
|
"""Wait until all containers reach 'healthy' or 'running' status.
|
|
408
457
|
|