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.
- {redeploy-0.2.68 → redeploy-0.2.69}/PKG-INFO +6 -6
- {redeploy-0.2.68 → redeploy-0.2.69}/README.md +5 -5
- {redeploy-0.2.68 → redeploy-0.2.69}/pyproject.toml +1 -1
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/__init__.py +1 -1
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/blueprint.py +6 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/steps/__init__.py +23 -2
- redeploy-0.2.69/redeploy/steps/docker.py +40 -0
- redeploy-0.2.69/redeploy/steps/generic.py +87 -0
- redeploy-0.2.69/redeploy/steps/hardware.py +22 -0
- redeploy-0.2.69/redeploy/steps/k3s.py +58 -0
- redeploy-0.2.69/redeploy/steps/podman.py +41 -0
- redeploy-0.2.69/redeploy/steps/process.py +32 -0
- redeploy-0.2.69/redeploy/steps/scm.py +22 -0
- redeploy-0.2.69/redeploy/steps/transfer.py +22 -0
- redeploy-0.2.69/redeploy/tests/test_steps_registry.py +109 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/PKG-INFO +6 -6
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/SOURCES.txt +9 -1
- redeploy-0.2.68/redeploy/steps/builtins.py +0 -275
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/checkers/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/preflight_schema.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/analyze/spec_analyzer.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/exceptions.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/executor.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/handlers.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/progress.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/rollback.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/state.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/state_apply.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/utils/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/apply/utils/run_container_build.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/audit.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/extractor.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/docker_compose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/generators/migration.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/compose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/hardware.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/infra.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/blueprint/sources/migration.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/audit.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/bump_fix.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/detect.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/device_map.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/device_map_renderers.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/devices.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/diagnose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/diff.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/exec_.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/export.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/hardware.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/import_.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/init.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/inspect.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/lint.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/mcp_cmd.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/patterns.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/plan_apply.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/plugin.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/probe.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/prompt_cmd.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/push.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/state.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/status.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/target.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/commands.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/helpers.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/monorepo.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/release.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/scanner.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/changelog_config.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/version/utils/git_config.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/commands/workflow.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/core.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/display.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli/query.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/cli.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/applier.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/config_apply/loader.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/data_sync.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/builtin/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/detector.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/hardware.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/hardware_rules.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/probes.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/remote.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/templates.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/detect/workflow.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/discovery.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/loader.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl/parser.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/context.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/decorators.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/docker_steps.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/exceptions.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/runner.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/dsl_python/steps.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/fleet.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/config_txt.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/hyperpixel.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/official.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/data/waveshare.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/fixes.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/autostart.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/browsers.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/compositors.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/kiosk/output_profiles.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/panels.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/hardware/raspi_config.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/decider.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/hint_provider.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/log_writer.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/loop_detector.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal/runner.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/heal.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/base.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/config_hints.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/docker_compose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/parsers/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/parsers/compose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/iac/registry.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/integrations/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/integrations/op3_bridge.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/compiler.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/models.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/markpact/parser.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/mcp_server.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/blueprint.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/devices.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/enums.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/hardware.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/infra.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/manifest.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/persisted.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/pipeline.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/plan.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/models/spec.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/observe.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/parse.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/patterns.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plan/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plan/planner.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/browser_reload.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/hardware_diagnostic.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/notify.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/process_control.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/plugins/builtin/systemd_reload.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/schema.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/spec_loader.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/ssh.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/steps/kiosk.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_analyze.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_audit.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_cli.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_data_sync.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_discovery.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_dsl.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_examples.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_executor.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_fleet.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_git_integration.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_heal.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_heal_decider.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_hooks.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac_compose_contract.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_iac_docker_compose_contract.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_manifest.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_markpact_compiler.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_markpact_parser.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_models.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_observe.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_parse.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_patterns.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_planner_edge.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_plugins.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_probes.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_public_api.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_resume.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_spec_loader.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_ssh.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_templates.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_verify.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_changelog.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_cli.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_manifest.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_version_sources.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/tests/test_workflow.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/verify.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/bump.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/changelog.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/commits.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/diff.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/git_integration.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/git_transaction.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/manifest.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/__init__.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/base.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/json_.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/plain.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/regex.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/toml_.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/sources/yaml_.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version/transaction.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy/version.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/dependency_links.txt +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/entry_points.txt +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/requires.txt +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/redeploy.egg-info/top_level.txt +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/setup.cfg +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_blueprint_sources.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_blueprint_sources_compose.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_cli_query.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_argocd_flux_plugin.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_gitops_ci_plugin.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_example_helm_kustomize_plugin.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_config.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_kiosk.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_hardware_rules.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_heal_decider.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_heal_loop_detector.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac_config_hints.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_iac_plugin_loading.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_import_plugin_template.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_parse.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_prompt_llm.py +0 -0
- {redeploy-0.2.68 → redeploy-0.2.69}/tests/test_redeploy.py +0 -0
- {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.
|
|
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
|
-
     
|
|
36
|
+
  
|
|
37
37
|
|
|
38
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
39
|
-
- 👤 **Human dev:** ~$
|
|
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
|
-
    
|
|
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
|
-
     
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
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
|
-
    
|
|
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.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
|
|
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
|
|
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.
|
|
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
|
-
     
|
|
36
|
+
  
|
|
37
37
|
|
|
38
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
39
|
-
- 👤 **Human dev:** ~$
|
|
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
|
-
    
|
|
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/
|
|
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
|