rosotacom-dev 2.5.dev6__tar.gz → 2.5.dev7__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.
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/PKG-INFO +23 -1
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/README.md +22 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/cli.py +211 -30
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/PKG-INFO +23 -1
- rosotacom_dev-2.5.dev7/src/rosotacom_dev.egg-info/scm_version.json +8 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_cli.py +128 -1
- rosotacom_dev-2.5.dev6/src/rosotacom_dev.egg-info/scm_version.json +0 -8
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/install.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/justfile +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/run_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/session-configuration.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/SOURCES.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/scm_file_list.json +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/stop_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_security_maintenance_config.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/conftest.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev6 → rosotacom_dev-2.5.dev7}/tests/unit/test_video_quality.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev7
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -460,6 +460,11 @@ rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
|
460
460
|
--install-mode pin # defaults to your own version
|
|
461
461
|
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
462
462
|
--install-mode pin --install-pin 2.4
|
|
463
|
+
|
|
464
|
+
# test the machines as they are: no staging, no install, their own checkouts
|
|
465
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
466
|
+
--peer-ssh b=robot-b --install-mode checkout \
|
|
467
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt
|
|
463
468
|
```
|
|
464
469
|
|
|
465
470
|
`source` is right while iterating on rosotacom itself — the peers run the code
|
|
@@ -469,6 +474,23 @@ missing from the wheel, an undeclared dependency) fails in the rehearsal instead
|
|
|
469
474
|
of on the target machine. `source` cannot catch that class of defect by
|
|
470
475
|
construction, because it never builds the artefact that ships.
|
|
471
476
|
|
|
477
|
+
`checkout` answers a different question again: not "does this artefact work" but
|
|
478
|
+
"is *this machine* ready". Nothing is staged and nothing is installed — each
|
|
479
|
+
peer runs the rosotacom it already has, from the project checkout it already
|
|
480
|
+
has, so what is under test is the state git and the machine's own install left
|
|
481
|
+
behind, dependency pins included. Ground truth moves into the repository: push,
|
|
482
|
+
pull, run. It is also the only mode in which a project may reference anything
|
|
483
|
+
outside its own directory — staging copies the project directory, so a mount or
|
|
484
|
+
config path leading above it cannot survive the copy and fails on the peer as a
|
|
485
|
+
missing path.
|
|
486
|
+
|
|
487
|
+
Because the same repository sits at a different absolute path on every machine,
|
|
488
|
+
`--peer-checkout` is required for every peer; the path *inside* the repository
|
|
489
|
+
is taken from your own checkout, so the project has to live in one. Preparation
|
|
490
|
+
becomes verification: each peer is asked whether the checkout, the project file
|
|
491
|
+
and `rosotacom` are there, and each version is printed. `--cleanup` does nothing
|
|
492
|
+
in this mode — there is no staging to undo, and the workdir is your repository.
|
|
493
|
+
|
|
472
494
|
The run manifest records which mode and which version the peers ran, so a result
|
|
473
495
|
can be attributed to an artefact rather than to a working copy.
|
|
474
496
|
|
|
@@ -415,6 +415,11 @@ rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
|
415
415
|
--install-mode pin # defaults to your own version
|
|
416
416
|
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
417
417
|
--install-mode pin --install-pin 2.4
|
|
418
|
+
|
|
419
|
+
# test the machines as they are: no staging, no install, their own checkouts
|
|
420
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
421
|
+
--peer-ssh b=robot-b --install-mode checkout \
|
|
422
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt
|
|
418
423
|
```
|
|
419
424
|
|
|
420
425
|
`source` is right while iterating on rosotacom itself — the peers run the code
|
|
@@ -424,6 +429,23 @@ missing from the wheel, an undeclared dependency) fails in the rehearsal instead
|
|
|
424
429
|
of on the target machine. `source` cannot catch that class of defect by
|
|
425
430
|
construction, because it never builds the artefact that ships.
|
|
426
431
|
|
|
432
|
+
`checkout` answers a different question again: not "does this artefact work" but
|
|
433
|
+
"is *this machine* ready". Nothing is staged and nothing is installed — each
|
|
434
|
+
peer runs the rosotacom it already has, from the project checkout it already
|
|
435
|
+
has, so what is under test is the state git and the machine's own install left
|
|
436
|
+
behind, dependency pins included. Ground truth moves into the repository: push,
|
|
437
|
+
pull, run. It is also the only mode in which a project may reference anything
|
|
438
|
+
outside its own directory — staging copies the project directory, so a mount or
|
|
439
|
+
config path leading above it cannot survive the copy and fails on the peer as a
|
|
440
|
+
missing path.
|
|
441
|
+
|
|
442
|
+
Because the same repository sits at a different absolute path on every machine,
|
|
443
|
+
`--peer-checkout` is required for every peer; the path *inside* the repository
|
|
444
|
+
is taken from your own checkout, so the project has to live in one. Preparation
|
|
445
|
+
becomes verification: each peer is asked whether the checkout, the project file
|
|
446
|
+
and `rosotacom` are there, and each version is printed. `--cleanup` does nothing
|
|
447
|
+
in this mode — there is no staging to undo, and the workdir is your repository.
|
|
448
|
+
|
|
427
449
|
The run manifest records which mode and which version the peers ran, so a result
|
|
428
450
|
can be attributed to an artefact rather than to a working copy.
|
|
429
451
|
|
|
@@ -125,9 +125,25 @@ OTA_SUDO_MODES = ("passwordless", "askpass")
|
|
|
125
125
|
# that ships, so a packaging defect — a file missing from the wheel, an
|
|
126
126
|
# undeclared dependency — fails here rather than on a Versuchsträger. `source`
|
|
127
127
|
# cannot catch that class of bug by construction.
|
|
128
|
-
|
|
128
|
+
#
|
|
129
|
+
# `checkout` is the third answer, and it inverts the question: nothing is
|
|
130
|
+
# staged and nothing is installed. Each peer runs the rosotacom it already has
|
|
131
|
+
# from the project checkout it already has, so what is under test is the state
|
|
132
|
+
# git put on that machine — including its dependency pins. `pin` still proves
|
|
133
|
+
# the artefact ships correctly; only `checkout` proves *this machine* is ready,
|
|
134
|
+
# which is what a deployment rehearsal actually asks. It is also the only mode
|
|
135
|
+
# in which a project may reference anything outside its own directory: staging
|
|
136
|
+
# copies the project directory, so a path leading above it cannot survive.
|
|
137
|
+
OTA_INSTALL_MODES = ("source", "pin", "checkout")
|
|
129
138
|
OTA_DEFAULT_SUDO_MODE = "passwordless"
|
|
130
139
|
|
|
140
|
+
# `ssh host 'cmd'` runs a non-login shell, so a pipx install in ~/.local/bin is
|
|
141
|
+
# not on PATH and the peer answers `rosotacom: command not found` — which reads
|
|
142
|
+
# as a broken machine rather than a missing PATH entry. The staged modes never
|
|
143
|
+
# meet this because they call an absolute path inside the workdir; checkout mode
|
|
144
|
+
# calls the peer's own command by name, so it has to say where that lives.
|
|
145
|
+
OTA_CHECKOUT_PATH_PREFIX = 'export PATH="$HOME/.local/bin:$PATH"; '
|
|
146
|
+
|
|
131
147
|
ws_creation_dir = WS_DIR / "session" / "creation"
|
|
132
148
|
session_gen_path = ws_creation_dir / "generate_session_files.py"
|
|
133
149
|
spec = importlib.util.spec_from_file_location("session_gen", session_gen_path)
|
|
@@ -212,6 +228,12 @@ class OtaSmokePeer:
|
|
|
212
228
|
name: str
|
|
213
229
|
ssh: str | None
|
|
214
230
|
address: str
|
|
231
|
+
#: Absolute path of this peer's project checkout, in `checkout` install mode
|
|
232
|
+
#: only. Per peer rather than one plan-wide value because the same
|
|
233
|
+
#: repository lives at a different absolute path on every machine — a
|
|
234
|
+
#: control centre runs it under a different account than a laptop does — and
|
|
235
|
+
#: a single workdir would silently be wrong on all but one of them.
|
|
236
|
+
checkout: str | None = None
|
|
215
237
|
|
|
216
238
|
|
|
217
239
|
@dataclass(frozen=True)
|
|
@@ -1001,6 +1023,10 @@ def _parse_peer_ssh_overrides(overrides: list[str] | None) -> dict[str, str]:
|
|
|
1001
1023
|
return parse_assignments(overrides, option="--peer-ssh")
|
|
1002
1024
|
|
|
1003
1025
|
|
|
1026
|
+
def _parse_peer_checkout_overrides(overrides: list[str] | None) -> dict[str, str]:
|
|
1027
|
+
return parse_assignments(overrides, option="--peer-checkout")
|
|
1028
|
+
|
|
1029
|
+
|
|
1004
1030
|
def _deployment_config(runtime: RuntimeConfig) -> DeploymentConfig | None:
|
|
1005
1031
|
return load_deployment(runtime.deployment)
|
|
1006
1032
|
|
|
@@ -1500,18 +1526,65 @@ def _ota_validate_install_mode(install_mode: str) -> str:
|
|
|
1500
1526
|
|
|
1501
1527
|
def _ota_rosotacom_path(install_mode: str) -> str:
|
|
1502
1528
|
"""Where the peer's rosotacom executable lands, relative to the workdir."""
|
|
1529
|
+
if install_mode == "checkout":
|
|
1530
|
+
# Not a path: the peer's own installation, whatever put it there. Naming
|
|
1531
|
+
# a path here would re-introduce the thing this mode removes — an
|
|
1532
|
+
# assumption by the orchestrator about the peer's file system.
|
|
1533
|
+
return "rosotacom"
|
|
1503
1534
|
return "venv/bin/rosotacom" if install_mode == "pin" else "source/.venv/bin/rosotacom"
|
|
1504
1535
|
|
|
1505
1536
|
|
|
1537
|
+
def _ota_checkout_project_path(project_config: Path) -> tuple[Path, str]:
|
|
1538
|
+
"""Split an active `rosotacom.yaml` into (checkout root, path inside it).
|
|
1539
|
+
|
|
1540
|
+
Checkout mode needs one repository-relative project path that is valid on
|
|
1541
|
+
every peer, and the honest source for it is the local checkout: walk up from
|
|
1542
|
+
the config until a `.git` entry appears. That is not a heuristic here — a
|
|
1543
|
+
mode whose ground truth is "what git put on the machine" is entitled to
|
|
1544
|
+
require that the project is in a repository, and requiring it makes the
|
|
1545
|
+
failure legible instead of producing a path that happens to be wrong on the
|
|
1546
|
+
other machine.
|
|
1547
|
+
"""
|
|
1548
|
+
config = project_config.resolve()
|
|
1549
|
+
for candidate in config.parents:
|
|
1550
|
+
if (candidate / ".git").exists():
|
|
1551
|
+
return candidate, config.relative_to(candidate).as_posix()
|
|
1552
|
+
raise RuntimeError(
|
|
1553
|
+
f"--install-mode checkout needs the project to live in a git checkout, and {config} is not in one. "
|
|
1554
|
+
"The peers resolve the project by its path inside the repository, so there has to be a repository."
|
|
1555
|
+
)
|
|
1556
|
+
|
|
1557
|
+
|
|
1506
1558
|
def _ota_plan_from_bindings(
|
|
1507
1559
|
bindings: dict[str, PeerBinding],
|
|
1508
1560
|
*,
|
|
1509
1561
|
workdir: str,
|
|
1510
1562
|
install_mode: str = "source",
|
|
1511
1563
|
install_pin: str | None = None,
|
|
1564
|
+
checkouts: Mapping[str, str] | None = None,
|
|
1565
|
+
project: str | None = None,
|
|
1512
1566
|
) -> OtaSmokePlan:
|
|
1513
|
-
_ota_validate_prepare_workdir(workdir)
|
|
1514
1567
|
_ota_validate_install_mode(install_mode)
|
|
1568
|
+
if install_mode == "checkout":
|
|
1569
|
+
if not checkouts or not project:
|
|
1570
|
+
raise RuntimeError("--install-mode checkout requires --peer-checkout for every peer.")
|
|
1571
|
+
missing = sorted(set(bindings) - set(checkouts))
|
|
1572
|
+
if missing:
|
|
1573
|
+
raise RuntimeError(
|
|
1574
|
+
"--install-mode checkout needs a checkout for every peer; missing: "
|
|
1575
|
+
+ ", ".join(f"--peer-checkout {name}=<path>" for name in missing)
|
|
1576
|
+
)
|
|
1577
|
+
unknown = sorted(set(checkouts) - set(bindings))
|
|
1578
|
+
if unknown:
|
|
1579
|
+
raise RuntimeError(f"--peer-checkout names a peer the session does not have: {', '.join(unknown)}")
|
|
1580
|
+
for name, path in sorted(checkouts.items()):
|
|
1581
|
+
if not path.startswith("/"):
|
|
1582
|
+
raise RuntimeError(f"--peer-checkout {name}={path}: a peer checkout must be an absolute path.")
|
|
1583
|
+
_ota_validate_prepare_workdir(path)
|
|
1584
|
+
else:
|
|
1585
|
+
_ota_validate_prepare_workdir(workdir)
|
|
1586
|
+
if checkouts:
|
|
1587
|
+
raise RuntimeError("--peer-checkout only applies to --install-mode checkout.")
|
|
1515
1588
|
if install_mode == "pin":
|
|
1516
1589
|
# Defaulting to the caller's own version makes `--install-mode pin`
|
|
1517
1590
|
# mean "rehearse what I am running, as it ships" without a second flag.
|
|
@@ -1524,13 +1597,19 @@ def _ota_plan_from_bindings(
|
|
|
1524
1597
|
elif install_pin is not None:
|
|
1525
1598
|
raise RuntimeError("--install-pin only applies to --install-mode pin.")
|
|
1526
1599
|
peers = {
|
|
1527
|
-
name: OtaSmokePeer(
|
|
1600
|
+
name: OtaSmokePeer(
|
|
1601
|
+
name=name,
|
|
1602
|
+
ssh=binding.ssh,
|
|
1603
|
+
address=binding.address,
|
|
1604
|
+
checkout=(checkouts or {}).get(name) if install_mode == "checkout" else None,
|
|
1605
|
+
)
|
|
1606
|
+
for name, binding in bindings.items()
|
|
1528
1607
|
}
|
|
1529
1608
|
return OtaSmokePlan(
|
|
1530
1609
|
state_path=None,
|
|
1531
1610
|
workdir=workdir,
|
|
1532
1611
|
rosotacom=_ota_rosotacom_path(install_mode),
|
|
1533
|
-
project="project/rosotacom.yaml",
|
|
1612
|
+
project=(project or "") if install_mode == "checkout" else "project/rosotacom.yaml",
|
|
1534
1613
|
peers=peers,
|
|
1535
1614
|
install_mode=install_mode,
|
|
1536
1615
|
install_pin=install_pin,
|
|
@@ -1540,13 +1619,16 @@ def _ota_plan_from_bindings(
|
|
|
1540
1619
|
def _ota_write_state(instance: SessionInstance, plan: OtaSmokePlan) -> OtaSmokePlan:
|
|
1541
1620
|
path = instance.host_dir / "ota-deployment.yaml"
|
|
1542
1621
|
payload = {
|
|
1543
|
-
"schema_version":
|
|
1622
|
+
"schema_version": 3,
|
|
1544
1623
|
"workdir": plan.workdir,
|
|
1545
1624
|
"rosotacom": plan.rosotacom,
|
|
1546
1625
|
"project": plan.project,
|
|
1547
1626
|
"install_mode": plan.install_mode,
|
|
1548
1627
|
"install_pin": plan.install_pin,
|
|
1549
|
-
"peers": {
|
|
1628
|
+
"peers": {
|
|
1629
|
+
name: {"address": peer.address, "ssh": peer.ssh, "checkout": peer.checkout}
|
|
1630
|
+
for name, peer in sorted(plan.peers.items())
|
|
1631
|
+
},
|
|
1550
1632
|
}
|
|
1551
1633
|
path.write_text(yaml.safe_dump(payload, sort_keys=False), encoding="utf-8")
|
|
1552
1634
|
return replace(plan, state_path=path)
|
|
@@ -1555,7 +1637,7 @@ def _ota_write_state(instance: SessionInstance, plan: OtaSmokePlan) -> OtaSmokeP
|
|
|
1555
1637
|
def _ota_load_state(path_arg: str) -> OtaSmokePlan:
|
|
1556
1638
|
path = Path(path_arg).expanduser().resolve()
|
|
1557
1639
|
raw = _load_yaml_file(path)
|
|
1558
|
-
if raw.get("schema_version") !=
|
|
1640
|
+
if raw.get("schema_version") != 3:
|
|
1559
1641
|
raise RuntimeError(f"Unsupported OTA deployment state: {path}")
|
|
1560
1642
|
peers_raw = raw.get("peers")
|
|
1561
1643
|
if not isinstance(peers_raw, dict) or len(peers_raw) != 2:
|
|
@@ -1568,6 +1650,7 @@ def _ota_load_state(path_arg: str) -> OtaSmokePlan:
|
|
|
1568
1650
|
name=str(name),
|
|
1569
1651
|
address=str(peer_raw["address"]),
|
|
1570
1652
|
ssh=str(peer_raw["ssh"]) if peer_raw.get("ssh") else None,
|
|
1653
|
+
checkout=str(peer_raw["checkout"]) if peer_raw.get("checkout") else None,
|
|
1571
1654
|
)
|
|
1572
1655
|
install_pin = raw.get("install_pin")
|
|
1573
1656
|
return OtaSmokePlan(
|
|
@@ -1680,9 +1763,15 @@ def _ota_project_cli_args(plan: OtaSmokePlan) -> list[str]:
|
|
|
1680
1763
|
return ["--rosotacom-config", plan.project]
|
|
1681
1764
|
|
|
1682
1765
|
|
|
1683
|
-
def
|
|
1766
|
+
def _ota_peer_workdir(plan: OtaSmokePlan, peer: OtaSmokePeer) -> str:
|
|
1767
|
+
"""The directory a peer's commands run in: its checkout, or the staging dir."""
|
|
1768
|
+
return peer.checkout or plan.workdir
|
|
1769
|
+
|
|
1770
|
+
|
|
1771
|
+
def _ota_rosotacom_command(plan: OtaSmokePlan, parts: list[str], peer: OtaSmokePeer) -> str:
|
|
1684
1772
|
command = [plan.rosotacom, *parts, *_ota_project_cli_args(plan)]
|
|
1685
|
-
|
|
1773
|
+
prefix = OTA_CHECKOUT_PATH_PREFIX if plan.install_mode == "checkout" else ""
|
|
1774
|
+
return f"{prefix}cd {shlex.quote(_ota_peer_workdir(plan, peer))} && {_ota_quote_cmd(command)}"
|
|
1686
1775
|
|
|
1687
1776
|
|
|
1688
1777
|
def _ota_source_checkout() -> Path | None:
|
|
@@ -2248,11 +2337,27 @@ def _resolve_ota_smoke_context(
|
|
|
2248
2337
|
peer_address=getattr(args, "peer_address", None),
|
|
2249
2338
|
peer_ssh=getattr(args, "peer_ssh", None),
|
|
2250
2339
|
)
|
|
2340
|
+
install_mode = str(getattr(args, "install_mode", None) or "source")
|
|
2341
|
+
checkouts = _parse_peer_checkout_overrides(getattr(args, "peer_checkout", None))
|
|
2342
|
+
project: str | None = None
|
|
2343
|
+
if install_mode == "checkout":
|
|
2344
|
+
if not runtime.rosotacom_config:
|
|
2345
|
+
raise RuntimeError("--install-mode checkout requires an active rosotacom.yaml project.")
|
|
2346
|
+
local_checkout, project = _ota_checkout_project_path(runtime.rosotacom_config)
|
|
2347
|
+
for name, path in sorted(checkouts.items()):
|
|
2348
|
+
binding = bindings.get(name)
|
|
2349
|
+
if binding is not None and not binding.ssh and Path(path).resolve() != local_checkout:
|
|
2350
|
+
raise RuntimeError(
|
|
2351
|
+
f"--peer-checkout {name}={path} names the peer that runs on this machine, but the active "
|
|
2352
|
+
f"project lives in {local_checkout}. Point it there, or give that peer an SSH target."
|
|
2353
|
+
)
|
|
2251
2354
|
plan = _ota_plan_from_bindings(
|
|
2252
2355
|
bindings,
|
|
2253
2356
|
workdir=str(getattr(args, "workdir", None) or "/tmp/rosotacom_ota"),
|
|
2254
|
-
install_mode=
|
|
2357
|
+
install_mode=install_mode,
|
|
2255
2358
|
install_pin=getattr(args, "install_pin", None),
|
|
2359
|
+
checkouts=checkouts,
|
|
2360
|
+
project=project,
|
|
2256
2361
|
)
|
|
2257
2362
|
plan_peers = set(plan.peers)
|
|
2258
2363
|
target_peers = set(_peer_keys_from_cfg(target.cfg))
|
|
@@ -2643,10 +2748,62 @@ def _ota_remote_package_dir(peer: OtaSmokePeer, plan: OtaSmokePlan, *, dry_run:
|
|
|
2643
2748
|
return located
|
|
2644
2749
|
|
|
2645
2750
|
|
|
2751
|
+
def _ota_verify_checkouts(plan: OtaSmokePlan, *, dry_run: bool) -> None:
|
|
2752
|
+
"""Checkout mode's replacement for staging: assert, do not install.
|
|
2753
|
+
|
|
2754
|
+
Nothing is copied and nothing is installed, so the only thing that can go
|
|
2755
|
+
wrong is a peer that is not in the state the caller thinks it is in — an
|
|
2756
|
+
unsynced checkout, a rosotacom that never got installed, a project path that
|
|
2757
|
+
exists on the laptop and not on the other machine. Each of those has a
|
|
2758
|
+
distinct one-line failure here, before any container starts, rather than a
|
|
2759
|
+
confusing one an hour later.
|
|
2760
|
+
"""
|
|
2761
|
+
for peer in plan.peers.values():
|
|
2762
|
+
checkout = shlex.quote(_ota_peer_workdir(plan, peer))
|
|
2763
|
+
project = shlex.quote(plan.project)
|
|
2764
|
+
_ota_run(
|
|
2765
|
+
peer,
|
|
2766
|
+
f"test -d {checkout}",
|
|
2767
|
+
label=f"{peer.name}: project checkout {_ota_peer_workdir(plan, peer)}",
|
|
2768
|
+
dry_run=dry_run,
|
|
2769
|
+
batch=True,
|
|
2770
|
+
)
|
|
2771
|
+
_ota_run(
|
|
2772
|
+
peer,
|
|
2773
|
+
f"test -f {checkout}/{project}",
|
|
2774
|
+
label=f"{peer.name}: project config {plan.project} inside the checkout",
|
|
2775
|
+
dry_run=dry_run,
|
|
2776
|
+
batch=True,
|
|
2777
|
+
)
|
|
2778
|
+
_ota_run(
|
|
2779
|
+
peer,
|
|
2780
|
+
f"{OTA_CHECKOUT_PATH_PREFIX}command -v rosotacom >/dev/null 2>&1",
|
|
2781
|
+
label=f"{peer.name}: rosotacom installed",
|
|
2782
|
+
dry_run=dry_run,
|
|
2783
|
+
batch=True,
|
|
2784
|
+
)
|
|
2785
|
+
version = _ota_run(
|
|
2786
|
+
peer,
|
|
2787
|
+
f"{OTA_CHECKOUT_PATH_PREFIX}rosotacom --version",
|
|
2788
|
+
label=f"{peer.name}: rosotacom version",
|
|
2789
|
+
dry_run=dry_run,
|
|
2790
|
+
batch=True,
|
|
2791
|
+
check=False,
|
|
2792
|
+
)
|
|
2793
|
+
if not dry_run and version.returncode == 0:
|
|
2794
|
+
# Printed rather than enforced. Peers running different versions is
|
|
2795
|
+
# a real hazard, but it is also a legitimate mid-migration state,
|
|
2796
|
+
# and a check that refuses it would be the wrong place to find out.
|
|
2797
|
+
print(f"+ {peer.name}: rosotacom {version.stdout.strip() or 'unknown'}")
|
|
2798
|
+
|
|
2799
|
+
|
|
2646
2800
|
def _ota_prepare_hosts(args: argparse.Namespace, runtime: RuntimeConfig, plan: OtaSmokePlan) -> None:
|
|
2647
2801
|
if not runtime.rosotacom_config:
|
|
2648
2802
|
raise RuntimeError("ota-smoke requires an active rosotacom.yaml project.")
|
|
2649
2803
|
dry_run = bool(getattr(args, "dry_run", False))
|
|
2804
|
+
if plan.install_mode == "checkout":
|
|
2805
|
+
_ota_verify_checkouts(plan, dry_run=dry_run)
|
|
2806
|
+
return
|
|
2650
2807
|
from_pin = plan.install_mode == "pin"
|
|
2651
2808
|
source_checkout: Path | None = None
|
|
2652
2809
|
temporary_bundle: Path | None = None
|
|
@@ -2924,6 +3081,7 @@ def _ota_start_peers(
|
|
|
2924
3081
|
command = _ota_rosotacom_command(
|
|
2925
3082
|
plan,
|
|
2926
3083
|
_ota_start_parts(target, peer_name, instance_id, peer_args, mode=mode, link_trace_parts=link_trace_parts),
|
|
3084
|
+
peer,
|
|
2927
3085
|
)
|
|
2928
3086
|
_ota_run(peer, command, label=f"{peer_name}: start {target.name}", dry_run=dry_run)
|
|
2929
3087
|
|
|
@@ -2940,7 +3098,7 @@ def _ota_start_session_publishers(
|
|
|
2940
3098
|
peer_args = _ota_peer_address_args(plan)
|
|
2941
3099
|
for peer_name in sorted(plan.peers):
|
|
2942
3100
|
peer = plan.peers[peer_name]
|
|
2943
|
-
command = _ota_rosotacom_command(plan, _ota_publish_parts(target, peer_name, peer_args))
|
|
3101
|
+
command = _ota_rosotacom_command(plan, _ota_publish_parts(target, peer_name, peer_args), peer)
|
|
2944
3102
|
result = _ota_run(peer, command, label=f"{peer_name}: start synthetic publishers", dry_run=dry_run, check=False)
|
|
2945
3103
|
_print_completed_output(result)
|
|
2946
3104
|
if result.returncode != 0:
|
|
@@ -2958,7 +3116,7 @@ def _ota_stop_session_publishers(
|
|
|
2958
3116
|
peer_args = _ota_peer_address_args(plan)
|
|
2959
3117
|
for peer_name in sorted(plan.peers):
|
|
2960
3118
|
peer = plan.peers[peer_name]
|
|
2961
|
-
command = _ota_rosotacom_command(plan, _ota_publish_parts(target, peer_name, peer_args, stop=True))
|
|
3119
|
+
command = _ota_rosotacom_command(plan, _ota_publish_parts(target, peer_name, peer_args, stop=True), peer)
|
|
2962
3120
|
_ota_run(peer, command, label=f"{peer_name}: stop synthetic publishers", dry_run=dry_run, check=False)
|
|
2963
3121
|
|
|
2964
3122
|
|
|
@@ -2974,7 +3132,7 @@ def _ota_verify_delivery(
|
|
|
2974
3132
|
print("OTA smoke: running status/expectation checks on every peer.")
|
|
2975
3133
|
for peer_name in sorted(plan.peers):
|
|
2976
3134
|
peer = plan.peers[peer_name]
|
|
2977
|
-
command = _ota_rosotacom_command(plan, _ota_test_parts(target, instance_id, profile=profile))
|
|
3135
|
+
command = _ota_rosotacom_command(plan, _ota_test_parts(target, instance_id, profile=profile), peer)
|
|
2978
3136
|
result = _ota_run(peer, command, label=f"{peer_name}: rosotacom test", dry_run=dry_run, check=False)
|
|
2979
3137
|
if result.returncode != 0:
|
|
2980
3138
|
_ota_print_failure_output(f"{peer_name}: rosotacom test", result)
|
|
@@ -2997,14 +3155,14 @@ def _ota_verify_isolation(
|
|
|
2997
3155
|
peer_args = _ota_peer_address_args(plan)
|
|
2998
3156
|
errors: list[str] = []
|
|
2999
3157
|
print(f"OTA smoke: checking isolation from {source_name} to {receiver_name}.")
|
|
3000
|
-
publish = _ota_rosotacom_command(plan, _ota_probe_publish_parts(target, source_name, peer_args, stop=False))
|
|
3158
|
+
publish = _ota_rosotacom_command(plan, _ota_probe_publish_parts(target, source_name, peer_args, stop=False), source)
|
|
3001
3159
|
published = _ota_run(source, publish, label=f"{source_name}: publish isolation probe", dry_run=dry_run, check=False)
|
|
3002
3160
|
if published.returncode != 0:
|
|
3003
3161
|
_ota_print_failure_output(f"{source_name}: publish isolation probe", published)
|
|
3004
3162
|
errors.append(f"{source_name}: isolation probe publisher failed")
|
|
3005
3163
|
return errors
|
|
3006
3164
|
_print_completed_output(published)
|
|
3007
|
-
check = _ota_rosotacom_command(plan, _ota_probe_check_parts(target, receiver_name, peer_args))
|
|
3165
|
+
check = _ota_rosotacom_command(plan, _ota_probe_check_parts(target, receiver_name, peer_args), receiver)
|
|
3008
3166
|
checked = _ota_run(
|
|
3009
3167
|
receiver,
|
|
3010
3168
|
check,
|
|
@@ -3017,7 +3175,7 @@ def _ota_verify_isolation(
|
|
|
3017
3175
|
errors.append(f"{receiver_name}: isolation probe crossed OTA boundary")
|
|
3018
3176
|
else:
|
|
3019
3177
|
_print_completed_output(checked)
|
|
3020
|
-
stop = _ota_rosotacom_command(plan, _ota_probe_publish_parts(target, source_name, peer_args, stop=True))
|
|
3178
|
+
stop = _ota_rosotacom_command(plan, _ota_probe_publish_parts(target, source_name, peer_args, stop=True), source)
|
|
3021
3179
|
stopped = _ota_run(source, stop, label=f"{source_name}: stop isolation probe", dry_run=dry_run, check=False)
|
|
3022
3180
|
_print_completed_output(stopped)
|
|
3023
3181
|
return errors
|
|
@@ -3046,7 +3204,7 @@ def _ota_verify_content_integrity(
|
|
|
3046
3204
|
for receiver_name, receiver in plan.peers.items():
|
|
3047
3205
|
for topic, msg_type, field, expected in _content_integrity_specs(cfg, receiver_name):
|
|
3048
3206
|
parts = _ota_content_check_parts(target, receiver_name, peer_args, topic, msg_type, field, expected)
|
|
3049
|
-
cmd = _ota_rosotacom_command(plan, parts)
|
|
3207
|
+
cmd = _ota_rosotacom_command(plan, parts, receiver)
|
|
3050
3208
|
print(f"OTA smoke: checking content integrity for {receiver_name} {topic}.")
|
|
3051
3209
|
result = _ota_run(
|
|
3052
3210
|
receiver, cmd, label=f"{receiver_name}: content integrity {topic}", dry_run=dry_run, check=False
|
|
@@ -3067,16 +3225,16 @@ def _ota_collect_logs(
|
|
|
3067
3225
|
) -> None:
|
|
3068
3226
|
project = shlex.quote(plan.project)
|
|
3069
3227
|
instance_suffix = shlex.quote(f"*_{instance.instance_id}")
|
|
3070
|
-
script = (
|
|
3071
|
-
f"cd {shlex.quote(plan.workdir)} && "
|
|
3072
|
-
f"project_dir=$(dirname {project}) && "
|
|
3073
|
-
f'instance_dir=$(find "$project_dir/session-instances" -mindepth 2 -maxdepth 2 '
|
|
3074
|
-
f"-type d -name {instance_suffix} -print -quit 2>/dev/null) && "
|
|
3075
|
-
'if [ -n "$instance_dir" ]; then '
|
|
3076
|
-
'relative=${instance_dir#"$project_dir"/}; '
|
|
3077
|
-
'tar cz -C "$project_dir" "$relative" 2>/dev/null | base64; fi'
|
|
3078
|
-
)
|
|
3079
3228
|
for peer in plan.peers.values():
|
|
3229
|
+
script = (
|
|
3230
|
+
f"cd {shlex.quote(_ota_peer_workdir(plan, peer))} && "
|
|
3231
|
+
f"project_dir=$(dirname {project}) && "
|
|
3232
|
+
f'instance_dir=$(find "$project_dir/session-instances" -mindepth 2 -maxdepth 2 '
|
|
3233
|
+
f"-type d -name {instance_suffix} -print -quit 2>/dev/null) && "
|
|
3234
|
+
'if [ -n "$instance_dir" ]; then '
|
|
3235
|
+
'relative=${instance_dir#"$project_dir"/}; '
|
|
3236
|
+
'tar cz -C "$project_dir" "$relative" 2>/dev/null | base64; fi'
|
|
3237
|
+
)
|
|
3080
3238
|
result = _ota_run(peer, script, label=f"{peer.name}: collect session-instances", dry_run=dry_run, check=False)
|
|
3081
3239
|
if dry_run or not result.stdout.strip():
|
|
3082
3240
|
continue
|
|
@@ -3139,7 +3297,7 @@ def _ota_stop_peers(
|
|
|
3139
3297
|
peer_args = _ota_peer_address_args(plan)
|
|
3140
3298
|
for peer_name in sorted(plan.peers):
|
|
3141
3299
|
peer = plan.peers[peer_name]
|
|
3142
|
-
command = _ota_rosotacom_command(plan, _ota_stop_parts(target, peer_name, instance_id, peer_args))
|
|
3300
|
+
command = _ota_rosotacom_command(plan, _ota_stop_parts(target, peer_name, instance_id, peer_args), peer)
|
|
3143
3301
|
_ota_run(peer, command, label=f"{peer_name}: stop {target.name}", dry_run=dry_run, check=False)
|
|
3144
3302
|
|
|
3145
3303
|
|
|
@@ -3186,7 +3344,9 @@ def _ota_application_run_script(
|
|
|
3186
3344
|
) -> str:
|
|
3187
3345
|
communication_suffix = _sanitize_docker_name(f"_com_to_{_remote_peer_name(target.cfg, peer_name)}")
|
|
3188
3346
|
label = f"{peer_name}:{application.name}"
|
|
3189
|
-
command = _ota_rosotacom_command(
|
|
3347
|
+
command = _ota_rosotacom_command(
|
|
3348
|
+
plan, _ota_application_parts(target, peer_name, application, instance_id), plan.peers[peer_name]
|
|
3349
|
+
)
|
|
3190
3350
|
return (
|
|
3191
3351
|
f"{_ota_wait_for_running_container_suffix_script(communication_suffix, f'{peer_name}:communication')}; "
|
|
3192
3352
|
f"echo '[INFO] starting native application container:' {shlex.quote(label)}; "
|
|
@@ -3219,6 +3379,7 @@ def _ota_create_tmux(
|
|
|
3219
3379
|
mode="attach",
|
|
3220
3380
|
link_trace_parts=link_trace_parts,
|
|
3221
3381
|
),
|
|
3382
|
+
first_peer,
|
|
3222
3383
|
)
|
|
3223
3384
|
first_script = (
|
|
3224
3385
|
"set -e; "
|
|
@@ -3298,6 +3459,7 @@ def _ota_create_tmux(
|
|
|
3298
3459
|
mode="attach",
|
|
3299
3460
|
link_trace_parts=link_trace_parts,
|
|
3300
3461
|
),
|
|
3462
|
+
peer,
|
|
3301
3463
|
)
|
|
3302
3464
|
script = (
|
|
3303
3465
|
"set -e; "
|
|
@@ -3432,6 +3594,13 @@ def _list_ota_smoke(args: argparse.Namespace) -> int:
|
|
|
3432
3594
|
|
|
3433
3595
|
|
|
3434
3596
|
def _ota_cleanup_hosts(plan: OtaSmokePlan, *, dry_run: bool) -> None:
|
|
3597
|
+
if plan.install_mode == "checkout":
|
|
3598
|
+
# The workdir is the user's repository here. `rm -rf` on it would delete
|
|
3599
|
+
# a checkout with its untracked work — bags, instance artefacts, local
|
|
3600
|
+
# edits — to clean up files this mode never created. There is nothing to
|
|
3601
|
+
# remove: staging is what cleanup undoes, and staging did not happen.
|
|
3602
|
+
print("OTA smoke: nothing to clean up — checkout mode staged nothing.")
|
|
3603
|
+
return
|
|
3435
3604
|
_ota_validate_prepare_workdir(plan.workdir)
|
|
3436
3605
|
for peer in plan.peers.values():
|
|
3437
3606
|
_ota_run(
|
|
@@ -3497,7 +3666,7 @@ def _start_interactive_ota_smoke(args: argparse.Namespace) -> int:
|
|
|
3497
3666
|
print("Local control tmux prefix: Ctrl-b. Send the peer tmux/catmux prefix with Ctrl-b Ctrl-b.")
|
|
3498
3667
|
if target.target_type == "scenario":
|
|
3499
3668
|
for peer_name, peer in plan.peers.items():
|
|
3500
|
-
attach = _ota_rosotacom_command(plan, ["scenario", "attach", target.name, "--identity", peer_name])
|
|
3669
|
+
attach = _ota_rosotacom_command(plan, ["scenario", "attach", target.name, "--identity", peer_name], peer)
|
|
3501
3670
|
attach_cmd = _ota_quote_cmd(_ota_remote_argv(peer, attach, tty=bool(peer.ssh)))
|
|
3502
3671
|
print(f"Manual remote scenario reattach for {peer_name}: {attach_cmd}")
|
|
3503
3672
|
if mode == "attach":
|
|
@@ -8266,6 +8435,16 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
8266
8435
|
_add_peer_arg(ota_smoke_parser)
|
|
8267
8436
|
_add_peer_address_arg(ota_smoke_parser)
|
|
8268
8437
|
_add_peer_ssh_arg(ota_smoke_parser)
|
|
8438
|
+
ota_smoke_parser.add_argument(
|
|
8439
|
+
"--peer-checkout",
|
|
8440
|
+
action="append",
|
|
8441
|
+
default=[],
|
|
8442
|
+
metavar="PEER=PATH",
|
|
8443
|
+
help=(
|
|
8444
|
+
"Absolute path of a peer's project checkout, for --install-mode checkout. "
|
|
8445
|
+
"Required for every peer in that mode; the same repository is at a different path on each machine."
|
|
8446
|
+
),
|
|
8447
|
+
)
|
|
8269
8448
|
ota_smoke_parser.add_argument("--target-type", choices=["auto", "session", "scenario"], default="auto")
|
|
8270
8449
|
ota_smoke_parser.add_argument("--interactive", action="store_true", help="Open a local control tmux UI.")
|
|
8271
8450
|
ota_smoke_parser.add_argument("--stop", action="store_true", help="Stop an OTA smoke run.")
|
|
@@ -8289,7 +8468,9 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
8289
8468
|
help=(
|
|
8290
8469
|
"How the peers get rosotacom. 'source' (default) stages and installs what you are running — "
|
|
8291
8470
|
"right while iterating on rosotacom. 'pin' installs a published release from the index, so the "
|
|
8292
|
-
"peers run the artefact that ships — right when rehearsing a deployment."
|
|
8471
|
+
"peers run the artefact that ships — right when rehearsing a deployment. 'checkout' stages and "
|
|
8472
|
+
"installs nothing: each peer uses its own installed rosotacom and its own project checkout "
|
|
8473
|
+
"(see --peer-checkout), so the run tests the machines as git left them."
|
|
8293
8474
|
),
|
|
8294
8475
|
)
|
|
8295
8476
|
ota_smoke_parser.add_argument(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev7
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -460,6 +460,11 @@ rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
|
460
460
|
--install-mode pin # defaults to your own version
|
|
461
461
|
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
462
462
|
--install-mode pin --install-pin 2.4
|
|
463
|
+
|
|
464
|
+
# test the machines as they are: no staging, no install, their own checkouts
|
|
465
|
+
rosotacom ota-smoke 2_native_chatter --peer a=workstation --peer b=robot \
|
|
466
|
+
--peer-ssh b=robot-b --install-mode checkout \
|
|
467
|
+
--peer-checkout a=/home/me/fleet_mgmt --peer-checkout b=/home/robot/fleet_mgmt
|
|
463
468
|
```
|
|
464
469
|
|
|
465
470
|
`source` is right while iterating on rosotacom itself — the peers run the code
|
|
@@ -469,6 +474,23 @@ missing from the wheel, an undeclared dependency) fails in the rehearsal instead
|
|
|
469
474
|
of on the target machine. `source` cannot catch that class of defect by
|
|
470
475
|
construction, because it never builds the artefact that ships.
|
|
471
476
|
|
|
477
|
+
`checkout` answers a different question again: not "does this artefact work" but
|
|
478
|
+
"is *this machine* ready". Nothing is staged and nothing is installed — each
|
|
479
|
+
peer runs the rosotacom it already has, from the project checkout it already
|
|
480
|
+
has, so what is under test is the state git and the machine's own install left
|
|
481
|
+
behind, dependency pins included. Ground truth moves into the repository: push,
|
|
482
|
+
pull, run. It is also the only mode in which a project may reference anything
|
|
483
|
+
outside its own directory — staging copies the project directory, so a mount or
|
|
484
|
+
config path leading above it cannot survive the copy and fails on the peer as a
|
|
485
|
+
missing path.
|
|
486
|
+
|
|
487
|
+
Because the same repository sits at a different absolute path on every machine,
|
|
488
|
+
`--peer-checkout` is required for every peer; the path *inside* the repository
|
|
489
|
+
is taken from your own checkout, so the project has to live in one. Preparation
|
|
490
|
+
becomes verification: each peer is asked whether the checkout, the project file
|
|
491
|
+
and `rosotacom` are there, and each version is printed. `--cleanup` does nothing
|
|
492
|
+
in this mode — there is no staging to undo, and the workdir is your repository.
|
|
493
|
+
|
|
472
494
|
The run manifest records which mode and which version the peers ran, so a result
|
|
473
495
|
can be attributed to an artefact rather than to a working copy.
|
|
474
496
|
|