redeploy 0.2.13__tar.gz → 0.2.15__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.13 → redeploy-0.2.15}/PKG-INFO +6 -6
- {redeploy-0.2.13 → redeploy-0.2.15}/README.md +5 -5
- {redeploy-0.2.13 → redeploy-0.2.15}/pyproject.toml +1 -1
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/__init__.py +1 -1
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/apply/executor.py +2 -1
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/markpact/parser.py +1 -1
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_cli.py +4 -4
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_executor.py +7 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_markpact_compiler.py +7 -7
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_markpact_parser.py +1 -1
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_spec_loader.py +4 -4
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/PKG-INFO +6 -6
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/apply/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/cli.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/data_sync.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/detector.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/probes.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/remote.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/templates.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/detect/workflow.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/discovery.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl/loader.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl/parser.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/context.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/decorators.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/docker_steps.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/exceptions.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/runner.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/dsl_python/steps.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/fleet.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/base.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/docker_compose.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/parsers/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/parsers/compose.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/iac/registry.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/markpact/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/markpact/compiler.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/markpact/models.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/models.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/observe.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/parse.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/patterns.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plan/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plan/planner.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plugins/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plugins/builtin/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plugins/builtin/browser_reload.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plugins/builtin/notify.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/plugins/builtin/systemd_reload.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/spec_loader.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/ssh.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/steps.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_data_sync.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_discovery.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_dsl.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_examples.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_fleet.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_git_integration.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_iac.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_manifest.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_models.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_observe.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_parse.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_patterns.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_planner_edge.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_plugins.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_probes.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_public_api.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_ssh.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_templates.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_verify.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_version.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_version_changelog.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_version_cli.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_version_manifest.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_version_sources.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/tests/test_workflow.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/verify.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/bump.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/changelog.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/commits.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/diff.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/git_integration.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/git_transaction.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/manifest.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/__init__.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/base.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/json_.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/plain.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/regex.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/toml_.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/sources/yaml_.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version/transaction.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy/version.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/SOURCES.txt +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/dependency_links.txt +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/entry_points.txt +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/requires.txt +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/redeploy.egg-info/top_level.txt +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/setup.cfg +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/tests/test_iac.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/tests/test_parse.py +0 -0
- {redeploy-0.2.13 → redeploy-0.2.15}/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.15
|
|
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:** $
|
|
34
|
-
- 👤 **Human dev:** ~$
|
|
33
|
+
- 🤖 **LLM usage:** $5.1000 (34 commits)
|
|
34
|
+
- 👤 **Human dev:** ~$1124 (11.2h @ $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
|
-
    
|
|
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:** $
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $5.1000 (34 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$1124 (11.2h @ $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
|
-
    
|
|
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.15"
|
|
11
11
|
|
|
12
12
|
# ── Core models ───────────────────────────────────────────────────────────────
|
|
13
13
|
from .models import ( # noqa: F401
|
|
@@ -232,7 +232,8 @@ class Executor:
|
|
|
232
232
|
cmd = step.command
|
|
233
233
|
if not cmd:
|
|
234
234
|
raise StepError(step, "No command specified")
|
|
235
|
-
|
|
235
|
+
timeout = step.timeout or 300
|
|
236
|
+
r = self.probe.run(cmd, timeout=timeout)
|
|
236
237
|
step.result = r.out[:500]
|
|
237
238
|
if not r.ok:
|
|
238
239
|
raise StepError(step, f"exit={r.exit_code}: {r.stderr[:200]}")
|
|
@@ -42,7 +42,7 @@ def parse_markpact_text(text: str, *, path: str | Path = "migration.md") -> Mark
|
|
|
42
42
|
|
|
43
43
|
if not blocks:
|
|
44
44
|
raise MarkpactParseError(
|
|
45
|
-
f"No markpact blocks found in {source_path}. Expected fenced blocks like ```markpact:config
|
|
45
|
+
f"No markpact blocks found in {source_path}. Expected fenced blocks like ```yaml markpact:config."
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
return MarkpactDocument(path=source_path, blocks=blocks)
|
|
@@ -37,7 +37,7 @@ def _migration_markdown_supported() -> str:
|
|
|
37
37
|
"""\
|
|
38
38
|
# Markdown migration
|
|
39
39
|
|
|
40
|
-
```markpact:config
|
|
40
|
+
```yaml markpact:config
|
|
41
41
|
name: markdown migration
|
|
42
42
|
description: migration loaded from markpact markdown
|
|
43
43
|
source:
|
|
@@ -53,7 +53,7 @@ target:
|
|
|
53
53
|
remote_dir: ~/myapp
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
```markpact:steps
|
|
56
|
+
```yaml markpact:steps
|
|
57
57
|
extra_steps:
|
|
58
58
|
- id: sync_env
|
|
59
59
|
src: .env
|
|
@@ -68,7 +68,7 @@ def _migration_markdown_with_unsupported_block() -> str:
|
|
|
68
68
|
"""\
|
|
69
69
|
# Markdown migration
|
|
70
70
|
|
|
71
|
-
```markpact:config
|
|
71
|
+
```yaml markpact:config
|
|
72
72
|
name: markdown migration
|
|
73
73
|
source:
|
|
74
74
|
strategy: docker_full
|
|
@@ -83,7 +83,7 @@ target:
|
|
|
83
83
|
remote_dir: ~/myapp
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
```markpact:python
|
|
86
|
+
```python markpact:python
|
|
87
87
|
print("unsupported in phase 1")
|
|
88
88
|
```
|
|
89
89
|
"""
|
|
@@ -192,6 +192,13 @@ class TestRunSsh:
|
|
|
192
192
|
exc.run()
|
|
193
193
|
assert step.result == "result_value"
|
|
194
194
|
|
|
195
|
+
def test_uses_step_timeout(self):
|
|
196
|
+
step = _make_step("ssh_timeout", command="echo long", timeout=1234)
|
|
197
|
+
plan = _make_plan([step])
|
|
198
|
+
exc = _executor(plan)
|
|
199
|
+
exc.run()
|
|
200
|
+
assert exc.probe.run.call_args.kwargs["timeout"] == 1234
|
|
201
|
+
|
|
195
202
|
|
|
196
203
|
# ── _run_scp ──────────────────────────────────────────────────────────────────
|
|
197
204
|
|
|
@@ -12,7 +12,7 @@ def test_compile_markpact_document_yaml_subset_to_spec():
|
|
|
12
12
|
textwrap.dedent("""\
|
|
13
13
|
# Demo
|
|
14
14
|
|
|
15
|
-
```markpact:config
|
|
15
|
+
```yaml markpact:config
|
|
16
16
|
name: compiler test
|
|
17
17
|
source:
|
|
18
18
|
strategy: docker_full
|
|
@@ -27,7 +27,7 @@ def test_compile_markpact_document_yaml_subset_to_spec():
|
|
|
27
27
|
remote_dir: ~/myapp
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
```markpact:steps
|
|
30
|
+
```yaml markpact:steps
|
|
31
31
|
extra_steps:
|
|
32
32
|
- id: sync_env
|
|
33
33
|
src: .env
|
|
@@ -64,7 +64,7 @@ def test_compile_markpact_document_supports_toml_config_and_steps():
|
|
|
64
64
|
remote_dir = "~/myapp"
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
```markpact:steps
|
|
67
|
+
```toml markpact:steps
|
|
68
68
|
[[extra_steps]]
|
|
69
69
|
id = "wait_startup"
|
|
70
70
|
seconds = 5
|
|
@@ -85,7 +85,7 @@ def test_compile_markpact_document_rejects_unsupported_block_kind():
|
|
|
85
85
|
textwrap.dedent("""\
|
|
86
86
|
# Demo
|
|
87
87
|
|
|
88
|
-
```markpact:config
|
|
88
|
+
```yaml markpact:config
|
|
89
89
|
name: compiler test
|
|
90
90
|
source:
|
|
91
91
|
strategy: docker_full
|
|
@@ -98,7 +98,7 @@ def test_compile_markpact_document_rejects_unsupported_block_kind():
|
|
|
98
98
|
remote_dir: ~/myapp
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
```markpact:python
|
|
101
|
+
```python markpact:python
|
|
102
102
|
print("unsupported")
|
|
103
103
|
```
|
|
104
104
|
"""),
|
|
@@ -116,7 +116,7 @@ def test_compile_markpact_document_rejects_unsupported_step_keys():
|
|
|
116
116
|
textwrap.dedent("""\
|
|
117
117
|
# Demo
|
|
118
118
|
|
|
119
|
-
```markpact:config
|
|
119
|
+
```yaml markpact:config
|
|
120
120
|
name: compiler test
|
|
121
121
|
source:
|
|
122
122
|
strategy: docker_full
|
|
@@ -129,7 +129,7 @@ def test_compile_markpact_document_rejects_unsupported_step_keys():
|
|
|
129
129
|
remote_dir: ~/myapp
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
```markpact:steps
|
|
132
|
+
```yaml markpact:steps
|
|
133
133
|
extra_steps:
|
|
134
134
|
- id: install_docker
|
|
135
135
|
action: ssh_cmd
|
|
@@ -29,7 +29,7 @@ def _migration_markdown() -> str:
|
|
|
29
29
|
"""\
|
|
30
30
|
# Markdown migration
|
|
31
31
|
|
|
32
|
-
```markpact:config
|
|
32
|
+
```yaml markpact:config
|
|
33
33
|
name: loader markdown test
|
|
34
34
|
source:
|
|
35
35
|
strategy: docker_full
|
|
@@ -44,7 +44,7 @@ target:
|
|
|
44
44
|
remote_dir: ~/myapp
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
```markpact:steps
|
|
47
|
+
```yaml markpact:steps
|
|
48
48
|
extra_steps:
|
|
49
49
|
- id: wait_startup
|
|
50
50
|
seconds: 5
|
|
@@ -79,7 +79,7 @@ def test_load_migration_spec_rejects_unsupported_markdown_block(tmp_path):
|
|
|
79
79
|
textwrap.dedent("""\
|
|
80
80
|
# Markdown migration
|
|
81
81
|
|
|
82
|
-
```markpact:config
|
|
82
|
+
```yaml markpact:config
|
|
83
83
|
name: broken markdown test
|
|
84
84
|
source:
|
|
85
85
|
strategy: docker_full
|
|
@@ -92,7 +92,7 @@ def test_load_migration_spec_rejects_unsupported_markdown_block(tmp_path):
|
|
|
92
92
|
remote_dir: ~/myapp
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
```markpact:python
|
|
95
|
+
```python markpact:python
|
|
96
96
|
print("unsupported")
|
|
97
97
|
```
|
|
98
98
|
"""),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redeploy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.15
|
|
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:** $
|
|
34
|
-
- 👤 **Human dev:** ~$
|
|
33
|
+
- 🤖 **LLM usage:** $5.1000 (34 commits)
|
|
34
|
+
- 👤 **Human dev:** ~$1124 (11.2h @ $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
|
-
    
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|