redeploy 0.2.58__tar.gz → 0.2.59__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.58 → redeploy-0.2.59}/PKG-INFO +6 -6
- {redeploy-0.2.58 → redeploy-0.2.59}/README.md +5 -5
- {redeploy-0.2.58 → redeploy-0.2.59}/pyproject.toml +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/__init__.py +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/device_map_renderers.py +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/plan_apply.py +2 -2
- redeploy-0.2.59/redeploy/cli/commands/version/utils/__init__.py +8 -0
- redeploy-0.2.59/redeploy/cli/commands/version/utils/changelog_config.py +27 -0
- redeploy-0.2.59/redeploy/cli/commands/version/utils/git_config.py +27 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/core.py +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/display.py +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/workflow.py +1 -1
- redeploy-0.2.59/redeploy/models/__init__.py +121 -0
- redeploy-0.2.59/redeploy/models/devices.py +170 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plan/planner.py +1 -1
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/PKG-INFO +6 -6
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/SOURCES.txt +5 -1
- redeploy-0.2.58/redeploy/models.py +0 -1096
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/exceptions.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/executor.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/handlers.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/progress.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/rollback.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/state.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/state_apply.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/utils/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/apply/utils/run_container_build.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/audit.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/extractor.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/generators/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/generators/docker_compose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/generators/migration.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/sources/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/sources/compose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/sources/hardware.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/sources/infra.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/blueprint/sources/migration.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/audit.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/blueprint.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/bump_fix.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/detect.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/device_map.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/devices.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/diagnose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/diff.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/exec_.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/export.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/hardware.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/import_.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/init.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/inspect.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/mcp_cmd.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/patterns.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/plugin.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/probe.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/prompt_cmd.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/push.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/state.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/status.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/target.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/commands.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/helpers.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/monorepo.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/release.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/version/scanner.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/commands/workflow.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli/query.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/cli.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/config_apply/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/config_apply/applier.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/config_apply/loader.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/data_sync.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/builtin/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/detector.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/hardware.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/hardware_rules.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/probes.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/remote.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/detect/templates.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/discovery.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl/loader.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl/parser.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/context.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/decorators.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/docker_steps.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/exceptions.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/runner.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/dsl_python/steps.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/fleet.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/config_txt.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/data/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/data/hyperpixel.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/data/official.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/data/waveshare.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/fixes.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/kiosk/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/kiosk/autostart.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/kiosk/browsers.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/kiosk/compositors.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/kiosk/output_profiles.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/panels.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/hardware/raspi_config.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/decider.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/hint_provider.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/log_writer.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/loop_detector.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal/runner.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/heal.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/base.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/config_hints.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/docker_compose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/parsers/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/parsers/compose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/iac/registry.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/integrations/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/integrations/op3_bridge.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/markpact/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/markpact/compiler.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/markpact/models.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/markpact/parser.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/mcp_server.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/blueprint.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/enums.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/hardware.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/infra.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/manifest.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/persisted.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/pipeline.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/plan.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/models/spec.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/observe.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/parse.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/patterns.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plan/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/browser_reload.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/hardware_diagnostic.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/notify.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/process_control.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/plugins/builtin/systemd_reload.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/schema.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/spec_loader.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/ssh.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/steps/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/steps/builtins.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/steps/kiosk.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_audit.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_cli.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_data_sync.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_discovery.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_dsl.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_examples.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_executor.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_fleet.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_git_integration.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_heal.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_heal_decider.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_hooks.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_iac.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_iac_compose_contract.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_iac_docker_compose_contract.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_manifest.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_markpact_compiler.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_markpact_parser.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_models.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_observe.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_parse.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_patterns.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_planner_edge.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_plugins.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_probes.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_public_api.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_resume.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_spec_loader.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_ssh.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_templates.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_verify.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_version.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_version_changelog.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_version_cli.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_version_manifest.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_version_sources.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/tests/test_workflow.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/verify.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/bump.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/changelog.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/commits.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/diff.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/git_integration.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/git_transaction.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/manifest.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/__init__.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/base.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/json_.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/plain.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/regex.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/toml_.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/sources/yaml_.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version/transaction.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy/version.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/dependency_links.txt +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/entry_points.txt +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/requires.txt +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/redeploy.egg-info/top_level.txt +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/setup.cfg +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_blueprint_sources.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_blueprint_sources_compose.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_cli_query.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_example_argocd_flux_plugin.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_example_gitops_ci_plugin.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_example_helm_kustomize_plugin.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_hardware_config.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_hardware_kiosk.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_hardware_rules.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_heal_decider.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_heal_loop_detector.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_iac.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_iac_config_hints.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_iac_plugin_loading.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_import_plugin_template.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_parse.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_prompt_llm.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/tests/test_redeploy.py +0 -0
- {redeploy-0.2.58 → redeploy-0.2.59}/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.59
|
|
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 (79 commits)
|
|
39
|
+
- 👤 **Human dev:** ~$2897 (29.0h @ $100/h, 30min dedup)
|
|
40
40
|
|
|
41
41
|
Generated on 2026-04-21 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 (79 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$2897 (29.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.59"
|
|
11
11
|
|
|
12
12
|
# ── Core models ───────────────────────────────────────────────────────────────
|
|
13
13
|
from .models import ( # noqa: F401
|
|
@@ -147,7 +147,7 @@ def render_rich(console: Console, dm: "DeviceMap") -> None:
|
|
|
147
147
|
]
|
|
148
148
|
rt_str = " ".join(r for r in runtimes if r) or "—"
|
|
149
149
|
console.print(
|
|
150
|
-
f"\n[bold]Infra[/bold] strategy=[cyan]{infra.detected_strategy
|
|
150
|
+
f"\n[bold]Infra[/bold] strategy=[cyan]{infra.detected_strategy}[/cyan]"
|
|
151
151
|
f" version={infra.current_version or '?'} {rt_str}"
|
|
152
152
|
)
|
|
153
153
|
|
|
@@ -186,7 +186,7 @@ def migrate(ctx, host, app, domain, target, strategy, target_version,
|
|
|
186
186
|
state = d.run()
|
|
187
187
|
d.save(state, Path(infra_out))
|
|
188
188
|
console.print(
|
|
189
|
-
f" Strategy: {state.detected_strategy
|
|
189
|
+
f" Strategy: {state.detected_strategy} "
|
|
190
190
|
f" Version: {state.current_version or '?'} "
|
|
191
191
|
f" Conflicts: {len(state.conflicts)}"
|
|
192
192
|
)
|
|
@@ -412,7 +412,7 @@ def _perform_live_detect(console, spec):
|
|
|
412
412
|
)
|
|
413
413
|
state = d.run()
|
|
414
414
|
console.print(
|
|
415
|
-
f" detected: {state.detected_strategy
|
|
415
|
+
f" detected: {state.detected_strategy} "
|
|
416
416
|
f"version={state.current_version or '?'} "
|
|
417
417
|
f"conflicts={len(state.conflicts)}"
|
|
418
418
|
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Shared version-command utilities."""
|
|
2
|
+
from .git_config import resolve_package_release_git_config
|
|
3
|
+
from .changelog_config import resolve_package_release_changelog_config
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"resolve_package_release_git_config",
|
|
7
|
+
"resolve_package_release_changelog_config",
|
|
8
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Resolve changelog config for a package release."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def resolve_package_release_changelog_config(
|
|
8
|
+
manifest_model: Any,
|
|
9
|
+
package_name: str | None,
|
|
10
|
+
*,
|
|
11
|
+
allow_root_fallback: bool,
|
|
12
|
+
) -> Any:
|
|
13
|
+
"""Return the changelog config for *package_name* with optional root fallback."""
|
|
14
|
+
if not package_name:
|
|
15
|
+
return manifest_model.changelog
|
|
16
|
+
|
|
17
|
+
package_manifest = manifest_model.get_package(package_name)
|
|
18
|
+
if package_manifest is None:
|
|
19
|
+
raise ValueError(f"Package '{package_name}' not found in manifest")
|
|
20
|
+
|
|
21
|
+
if package_manifest.changelog is not None:
|
|
22
|
+
return package_manifest.changelog
|
|
23
|
+
|
|
24
|
+
if allow_root_fallback:
|
|
25
|
+
return manifest_model.changelog
|
|
26
|
+
|
|
27
|
+
return None
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Resolve git-config for a package release."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def resolve_package_release_git_config(
|
|
8
|
+
manifest_model: Any,
|
|
9
|
+
package_name: str | None,
|
|
10
|
+
*,
|
|
11
|
+
allow_root_fallback: bool,
|
|
12
|
+
) -> Any:
|
|
13
|
+
"""Return the git config for *package_name* with optional root fallback."""
|
|
14
|
+
if not package_name:
|
|
15
|
+
return manifest_model.git
|
|
16
|
+
|
|
17
|
+
package_manifest = manifest_model.get_package(package_name)
|
|
18
|
+
if package_manifest is None:
|
|
19
|
+
raise ValueError(f"Package '{package_name}' not found in manifest")
|
|
20
|
+
|
|
21
|
+
if package_manifest.git is not None:
|
|
22
|
+
return package_manifest.git
|
|
23
|
+
|
|
24
|
+
if allow_root_fallback:
|
|
25
|
+
return manifest_model.git
|
|
26
|
+
|
|
27
|
+
return None
|
|
@@ -126,7 +126,7 @@ def run_detect_for_spec(
|
|
|
126
126
|
d = Detector(host=spec.source.host, app=spec.source.app, domain=spec.source.domain)
|
|
127
127
|
state = d.run()
|
|
128
128
|
console.print(
|
|
129
|
-
f" detected: {state.detected_strategy
|
|
129
|
+
f" detected: {state.detected_strategy} "
|
|
130
130
|
f"version={state.current_version or '?'} "
|
|
131
131
|
f"conflicts={len(state.conflicts)}"
|
|
132
132
|
)
|
|
@@ -36,7 +36,7 @@ def print_infrastructure_summary(console: "Console", state, host: str) -> None:
|
|
|
36
36
|
t.add_column("key", style="dim")
|
|
37
37
|
t.add_column("value")
|
|
38
38
|
t.add_row("App", state.app)
|
|
39
|
-
t.add_row("Strategy (detected)", state.detected_strategy
|
|
39
|
+
t.add_row("Strategy (detected)", state.detected_strategy)
|
|
40
40
|
t.add_row("Version", state.current_version or "unknown")
|
|
41
41
|
t.add_row("Docker", state.runtime.docker or "—")
|
|
42
42
|
t.add_row("k3s", state.runtime.k3s or "—")
|
|
@@ -398,7 +398,7 @@ class DetectionWorkflow:
|
|
|
398
398
|
host_res = self._deep_detect(host_res)
|
|
399
399
|
if host_res.state:
|
|
400
400
|
logger.info(
|
|
401
|
-
f"[workflow] strategy={host_res.state.detected_strategy
|
|
401
|
+
f"[workflow] strategy={host_res.state.detected_strategy} "
|
|
402
402
|
f"ports={sorted(host_res.state.ports.keys())} "
|
|
403
403
|
f"conflicts={len(host_res.state.conflicts)}"
|
|
404
404
|
)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""redeploy.models — shared data models (backward-compat re-export hub).
|
|
2
|
+
|
|
3
|
+
This package was refactored from the monolithic ``redeploy.models`` module
|
|
4
|
+
(R3, 0.2.53). All public names remain importable from the top-level
|
|
5
|
+
package for backward compatibility.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
# ── core ─────────────────────────────────────────────────────────────────────
|
|
10
|
+
from .enums import (
|
|
11
|
+
ConflictSeverity,
|
|
12
|
+
DeployStrategy,
|
|
13
|
+
StepAction,
|
|
14
|
+
StepStatus,
|
|
15
|
+
_STRATEGY_ALIASES,
|
|
16
|
+
)
|
|
17
|
+
from .persisted import PersistedModel
|
|
18
|
+
|
|
19
|
+
# ── hardware ─────────────────────────────────────────────────────────────────
|
|
20
|
+
from .hardware import (
|
|
21
|
+
BacklightInfo,
|
|
22
|
+
DrmOutput,
|
|
23
|
+
HardwareDiagnostic,
|
|
24
|
+
HardwareInfo,
|
|
25
|
+
I2CBusInfo,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# ── infra state ─────────────────────────────────────────────────────────────
|
|
29
|
+
from .infra import (
|
|
30
|
+
AppHealthInfo,
|
|
31
|
+
ConflictInfo,
|
|
32
|
+
InfraState,
|
|
33
|
+
PortInfo,
|
|
34
|
+
RuntimeInfo,
|
|
35
|
+
ServiceInfo,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# ── pipeline ─────────────────────────────────────────────────────────────────
|
|
39
|
+
from .pipeline import Hook, PipelinePhase
|
|
40
|
+
|
|
41
|
+
# ── spec & target ───────────────────────────────────────────────────────────
|
|
42
|
+
from .spec import (
|
|
43
|
+
InfraSpec,
|
|
44
|
+
MigrationSpec,
|
|
45
|
+
TargetConfig,
|
|
46
|
+
_migrate_legacy_post_deploy,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# ── plan ─────────────────────────────────────────────────────────────────────
|
|
50
|
+
from .plan import MigrationPlan, MigrationStep
|
|
51
|
+
|
|
52
|
+
# ── manifest ─────────────────────────────────────────────────────────────────
|
|
53
|
+
from .manifest import EnvironmentConfig, ProjectManifest
|
|
54
|
+
|
|
55
|
+
# ── blueprint ────────────────────────────────────────────────────────────────
|
|
56
|
+
from .blueprint import (
|
|
57
|
+
BlueprintSource,
|
|
58
|
+
DeviceBlueprint,
|
|
59
|
+
HardwareRequirements,
|
|
60
|
+
ServicePort,
|
|
61
|
+
ServiceSpec,
|
|
62
|
+
VolumeMount,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# ── device registry / map ───────────────────────────────────────────────────
|
|
66
|
+
from .devices import (
|
|
67
|
+
DeployRecord,
|
|
68
|
+
DeviceMap,
|
|
69
|
+
DeviceRegistry,
|
|
70
|
+
KnownDevice,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
__all__ = [
|
|
74
|
+
# enums
|
|
75
|
+
"ConflictSeverity",
|
|
76
|
+
"DeployStrategy",
|
|
77
|
+
"StepAction",
|
|
78
|
+
"StepStatus",
|
|
79
|
+
"_STRATEGY_ALIASES",
|
|
80
|
+
# persisted
|
|
81
|
+
"PersistedModel",
|
|
82
|
+
# hardware
|
|
83
|
+
"BacklightInfo",
|
|
84
|
+
"DrmOutput",
|
|
85
|
+
"HardwareDiagnostic",
|
|
86
|
+
"HardwareInfo",
|
|
87
|
+
"I2CBusInfo",
|
|
88
|
+
# infra
|
|
89
|
+
"AppHealthInfo",
|
|
90
|
+
"ConflictInfo",
|
|
91
|
+
"InfraState",
|
|
92
|
+
"PortInfo",
|
|
93
|
+
"RuntimeInfo",
|
|
94
|
+
"ServiceInfo",
|
|
95
|
+
# pipeline
|
|
96
|
+
"Hook",
|
|
97
|
+
"PipelinePhase",
|
|
98
|
+
# spec
|
|
99
|
+
"InfraSpec",
|
|
100
|
+
"MigrationSpec",
|
|
101
|
+
"TargetConfig",
|
|
102
|
+
"_migrate_legacy_post_deploy",
|
|
103
|
+
# plan
|
|
104
|
+
"MigrationPlan",
|
|
105
|
+
"MigrationStep",
|
|
106
|
+
# manifest
|
|
107
|
+
"EnvironmentConfig",
|
|
108
|
+
"ProjectManifest",
|
|
109
|
+
# blueprint
|
|
110
|
+
"BlueprintSource",
|
|
111
|
+
"DeviceBlueprint",
|
|
112
|
+
"HardwareRequirements",
|
|
113
|
+
"ServicePort",
|
|
114
|
+
"ServiceSpec",
|
|
115
|
+
"VolumeMount",
|
|
116
|
+
# devices
|
|
117
|
+
"DeployRecord",
|
|
118
|
+
"DeviceMap",
|
|
119
|
+
"DeviceRegistry",
|
|
120
|
+
"KnownDevice",
|
|
121
|
+
]
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Device registry and device-map models."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
from pydantic import BaseModel, Field, PrivateAttr
|
|
10
|
+
|
|
11
|
+
from .hardware import HardwareInfo
|
|
12
|
+
from .infra import InfraState
|
|
13
|
+
from .persisted import PersistedModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_DEFAULT_DEVICE_MAP_DIR = Path.home() / ".config" / "redeploy" / "device-maps"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DeployRecord(BaseModel):
|
|
20
|
+
"""Single deployment event recorded for a device."""
|
|
21
|
+
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
22
|
+
spec_name: str = ""
|
|
23
|
+
from_strategy: str = ""
|
|
24
|
+
to_strategy: str = ""
|
|
25
|
+
version: str = ""
|
|
26
|
+
ok: bool = True
|
|
27
|
+
steps_total: int = 0
|
|
28
|
+
steps_ok: int = 0
|
|
29
|
+
note: str = ""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class KnownDevice(BaseModel):
|
|
33
|
+
"""Device known to redeploy — persisted in ~/.config/redeploy/devices.yaml."""
|
|
34
|
+
id: str
|
|
35
|
+
host: str = ""
|
|
36
|
+
name: str = ""
|
|
37
|
+
tags: list[str] = Field(default_factory=list)
|
|
38
|
+
strategy: str = "docker_full"
|
|
39
|
+
app: str = ""
|
|
40
|
+
domain: str = ""
|
|
41
|
+
remote_dir: str = ""
|
|
42
|
+
ssh_port: int = 22
|
|
43
|
+
ssh_key: Optional[str] = None
|
|
44
|
+
|
|
45
|
+
ip: str = ""
|
|
46
|
+
mac: str = ""
|
|
47
|
+
hostname: str = ""
|
|
48
|
+
ssh_user: str = ""
|
|
49
|
+
last_seen: Optional[datetime] = None
|
|
50
|
+
last_ssh_ok: Optional[datetime] = None
|
|
51
|
+
source: str = "manual"
|
|
52
|
+
|
|
53
|
+
hardware: Optional[HardwareInfo] = None
|
|
54
|
+
deploys: list[DeployRecord] = Field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def last_deploy(self) -> Optional[DeployRecord]:
|
|
58
|
+
return self.deploys[-1] if self.deploys else None
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def is_reachable(self) -> bool:
|
|
62
|
+
if self.last_seen is None:
|
|
63
|
+
return False
|
|
64
|
+
return (datetime.now(timezone.utc) - self.last_seen).total_seconds() < 300
|
|
65
|
+
|
|
66
|
+
def record_deploy(self, record: DeployRecord) -> None:
|
|
67
|
+
self.deploys.append(record)
|
|
68
|
+
self.deploys = self.deploys[-50:]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class DeviceMap(PersistedModel):
|
|
72
|
+
"""Full, persisted snapshot of a device: identity + InfraState + HardwareInfo."""
|
|
73
|
+
id: str
|
|
74
|
+
host: str = ""
|
|
75
|
+
name: str = ""
|
|
76
|
+
tags: list[str] = Field(default_factory=list)
|
|
77
|
+
scanned_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
|
78
|
+
|
|
79
|
+
hardware: Optional[HardwareInfo] = None
|
|
80
|
+
infra: Optional[InfraState] = None
|
|
81
|
+
issues: list[dict] = Field(default_factory=list)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def has_errors(self) -> bool:
|
|
85
|
+
return any(i.get("severity") in ("error", "critical") for i in self.issues)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def display_summary(self) -> str:
|
|
89
|
+
if not self.hardware:
|
|
90
|
+
return "no hardware data"
|
|
91
|
+
hw = self.hardware
|
|
92
|
+
dsi = next((o for o in hw.drm_outputs if "DSI" in o.name), None)
|
|
93
|
+
if dsi:
|
|
94
|
+
mode = dsi.modes[0] if dsi.modes else "?"
|
|
95
|
+
bl = hw.backlights[0].brightness if hw.backlights else "?"
|
|
96
|
+
return f"DSI {dsi.connector} {dsi.status} {mode} backlight={bl}"
|
|
97
|
+
return "no DSI"
|
|
98
|
+
|
|
99
|
+
def save(self, path: Optional[Path] = None) -> Path:
|
|
100
|
+
p = path or _DEFAULT_DEVICE_MAP_DIR / f"{self.id.replace('/', '_').replace('@', '_at_')}.yaml"
|
|
101
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
102
|
+
p.write_text(self.to_yaml())
|
|
103
|
+
return p
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def load_for(cls, device_id: str) -> Optional[DeviceMap]:
|
|
107
|
+
p = _DEFAULT_DEVICE_MAP_DIR / f"{device_id.replace('/', '_').replace('@', '_at_')}.yaml"
|
|
108
|
+
if p.exists():
|
|
109
|
+
return cls.load(p)
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def list_saved(cls) -> list[Path]:
|
|
114
|
+
if not _DEFAULT_DEVICE_MAP_DIR.exists():
|
|
115
|
+
return []
|
|
116
|
+
return sorted(_DEFAULT_DEVICE_MAP_DIR.glob("*.yaml"))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class DeviceRegistry(BaseModel):
|
|
120
|
+
"""Persistent device registry — stored at ~/.config/redeploy/devices.yaml."""
|
|
121
|
+
devices: list[KnownDevice] = Field(default_factory=list)
|
|
122
|
+
_path: Optional[Path] = PrivateAttr(default=None)
|
|
123
|
+
|
|
124
|
+
def get(self, device_id: str) -> Optional[KnownDevice]:
|
|
125
|
+
return next((d for d in self.devices if d.id == device_id), None)
|
|
126
|
+
|
|
127
|
+
def upsert(self, device: KnownDevice) -> None:
|
|
128
|
+
for i, d in enumerate(self.devices):
|
|
129
|
+
if d.id == device.id:
|
|
130
|
+
self.devices[i] = device
|
|
131
|
+
return
|
|
132
|
+
self.devices.append(device)
|
|
133
|
+
|
|
134
|
+
def remove(self, device_id: str) -> bool:
|
|
135
|
+
before = len(self.devices)
|
|
136
|
+
self.devices = [d for d in self.devices if d.id != device_id]
|
|
137
|
+
return len(self.devices) < before
|
|
138
|
+
|
|
139
|
+
def by_tag(self, tag: str) -> list[KnownDevice]:
|
|
140
|
+
return [d for d in self.devices if tag in d.tags]
|
|
141
|
+
|
|
142
|
+
def by_strategy(self, strategy: str) -> list[KnownDevice]:
|
|
143
|
+
return [d for d in self.devices if d.strategy == strategy]
|
|
144
|
+
|
|
145
|
+
def reachable(self) -> list[KnownDevice]:
|
|
146
|
+
return [d for d in self.devices if d.is_reachable]
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def default_path(cls) -> Path:
|
|
150
|
+
return Path.home() / ".config" / "redeploy" / "devices.yaml"
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def load(cls, path: Optional[Path] = None) -> DeviceRegistry:
|
|
154
|
+
p = path or cls.default_path()
|
|
155
|
+
if not p.exists():
|
|
156
|
+
return cls()
|
|
157
|
+
raw = yaml.safe_load(p.read_text()) or {}
|
|
158
|
+
devices = [KnownDevice(**d) for d in raw.get("devices", [])]
|
|
159
|
+
reg = cls(devices=devices)
|
|
160
|
+
reg._path = p
|
|
161
|
+
return reg
|
|
162
|
+
|
|
163
|
+
def save(self, path: Optional[Path] = None) -> None:
|
|
164
|
+
p = path or self._path or self.default_path()
|
|
165
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
166
|
+
data = {"devices": [d.model_dump(mode="json") for d in self.devices]}
|
|
167
|
+
tmp = p.with_suffix(".tmp")
|
|
168
|
+
tmp.write_text(yaml.dump(data, allow_unicode=True, sort_keys=False))
|
|
169
|
+
tmp.chmod(0o600)
|
|
170
|
+
tmp.replace(p)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redeploy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.59
|
|
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 (79 commits)
|
|
39
|
+
- 👤 **Human dev:** ~$2897 (29.0h @ $100/h, 30min dedup)
|
|
40
40
|
|
|
41
41
|
Generated on 2026-04-21 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
|
|
|
@@ -8,7 +8,6 @@ redeploy/discovery.py
|
|
|
8
8
|
redeploy/fleet.py
|
|
9
9
|
redeploy/heal.py
|
|
10
10
|
redeploy/mcp_server.py
|
|
11
|
-
redeploy/models.py
|
|
12
11
|
redeploy/observe.py
|
|
13
12
|
redeploy/parse.py
|
|
14
13
|
redeploy/patterns.py
|
|
@@ -80,6 +79,9 @@ redeploy/cli/commands/version/helpers.py
|
|
|
80
79
|
redeploy/cli/commands/version/monorepo.py
|
|
81
80
|
redeploy/cli/commands/version/release.py
|
|
82
81
|
redeploy/cli/commands/version/scanner.py
|
|
82
|
+
redeploy/cli/commands/version/utils/__init__.py
|
|
83
|
+
redeploy/cli/commands/version/utils/changelog_config.py
|
|
84
|
+
redeploy/cli/commands/version/utils/git_config.py
|
|
83
85
|
redeploy/config_apply/__init__.py
|
|
84
86
|
redeploy/config_apply/applier.py
|
|
85
87
|
redeploy/config_apply/loader.py
|
|
@@ -135,7 +137,9 @@ redeploy/markpact/__init__.py
|
|
|
135
137
|
redeploy/markpact/compiler.py
|
|
136
138
|
redeploy/markpact/models.py
|
|
137
139
|
redeploy/markpact/parser.py
|
|
140
|
+
redeploy/models/__init__.py
|
|
138
141
|
redeploy/models/blueprint.py
|
|
142
|
+
redeploy/models/devices.py
|
|
139
143
|
redeploy/models/enums.py
|
|
140
144
|
redeploy/models/hardware.py
|
|
141
145
|
redeploy/models/infra.py
|