rosotacom-dev 2.5.dev21__tar.gz → 2.5.dev23__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.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/pr-merge-gate.yml +111 -2
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/PKG-INFO +28 -2
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/README.md +26 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/ci.md +69 -6
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/pyproject.toml +1 -1
- rosotacom_dev-2.5.dev23/requirements.txt +1 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/cli.py +133 -3
- rosotacom_dev-2.5.dev23/src/rosotacom/image_cache.py +169 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/PKG-INFO +28 -2
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/SOURCES.txt +2 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/requires.txt +1 -1
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/scm_file_list.json +2 -0
- rosotacom_dev-2.5.dev23/src/rosotacom_dev.egg-info/scm_version.json +8 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_security_maintenance_config.py +8 -2
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_workflow_contracts.py +23 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/conftest.py +23 -9
- rosotacom_dev-2.5.dev23/tests/unit/test_image_cache.py +262 -0
- rosotacom_dev-2.5.dev21/requirements.txt +0 -1
- rosotacom_dev-2.5.dev21/src/rosotacom_dev.egg-info/scm_version.json +0 -8
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/install.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/justfile +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/run_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/session-configuration.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/stop_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/contract/test_session_configuration_doc.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_cli.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev21 → rosotacom_dev-2.5.dev23}/tests/unit/test_video_quality.py +0 -0
|
@@ -192,6 +192,96 @@ jobs:
|
|
|
192
192
|
fi
|
|
193
193
|
echo "All preflight checks passed"
|
|
194
194
|
|
|
195
|
+
image:
|
|
196
|
+
# Publish the images the e2e suite builds, once per set of build inputs,
|
|
197
|
+
# instead of rebuilding them in each of thirteen jobs. #236 measured that
|
|
198
|
+
# build at 154s per job: 57s pulling the multi-GB ROS base from Docker Hub,
|
|
199
|
+
# 40s exporting layers, 47s of apt and pip. A pull from GHCR — co-located
|
|
200
|
+
# with the runners, no Hub rate limit, one transfer instead of a transfer
|
|
201
|
+
# plus a build — replaces all of it, and takes twelve of the thirteen Hub
|
|
202
|
+
# pulls off the merge gate's critical path.
|
|
203
|
+
#
|
|
204
|
+
# The tag is a hash of everything that decides the image (base digest,
|
|
205
|
+
# package lists, Dockerfile, entrypoint, ros2docker version, build UID):
|
|
206
|
+
# `rosotacom image references` derives it, nothing here chooses it. A
|
|
207
|
+
# build-input change is therefore a different tag, so "the published image
|
|
208
|
+
# is stale" is not a state this can reach — which is the objection #226
|
|
209
|
+
# raised against caching the image inline.
|
|
210
|
+
#
|
|
211
|
+
# Runs beside preflight rather than after it: on a hit it inspects two
|
|
212
|
+
# manifests and stops, so it is never on the critical path.
|
|
213
|
+
name: image
|
|
214
|
+
runs-on: ubuntu-latest
|
|
215
|
+
timeout-minutes: 60
|
|
216
|
+
if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
|
|
217
|
+
permissions:
|
|
218
|
+
contents: read
|
|
219
|
+
packages: write
|
|
220
|
+
outputs:
|
|
221
|
+
repository: ${{ steps.publish.outputs.repository }}
|
|
222
|
+
|
|
223
|
+
steps:
|
|
224
|
+
- name: Check out repository
|
|
225
|
+
uses: actions/checkout@v6
|
|
226
|
+
|
|
227
|
+
- name: Set up Python
|
|
228
|
+
uses: actions/setup-python@v6
|
|
229
|
+
with:
|
|
230
|
+
python-version: "3.12"
|
|
231
|
+
cache: pip
|
|
232
|
+
|
|
233
|
+
- name: Install just
|
|
234
|
+
run: |
|
|
235
|
+
sudo apt-get update
|
|
236
|
+
sudo apt-get install -y just
|
|
237
|
+
|
|
238
|
+
- name: Set up local environment
|
|
239
|
+
run: just setup
|
|
240
|
+
|
|
241
|
+
- name: Log in to GHCR
|
|
242
|
+
run: echo '${{ secrets.GITHUB_TOKEN }}' | docker login ghcr.io -u '${{ github.actor }}' --password-stdin
|
|
243
|
+
|
|
244
|
+
- name: Publish every image the e2e suite builds
|
|
245
|
+
id: publish
|
|
246
|
+
run: |
|
|
247
|
+
set -euo pipefail
|
|
248
|
+
repository="ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')/rosotacom-e2e"
|
|
249
|
+
# The packaged example project, because that is the one the e2e tests
|
|
250
|
+
# copy. The repository's own rosotacom.yaml points at profiles and
|
|
251
|
+
# artifacts that live beside the checkout in the private harness, so it
|
|
252
|
+
# does not resolve here.
|
|
253
|
+
project="$(.venv/bin/rosotacom resources path examples)/rosotacom.yaml"
|
|
254
|
+
.venv/bin/rosotacom image references --project "$project" --repository "$repository" > references.txt
|
|
255
|
+
cat references.txt
|
|
256
|
+
|
|
257
|
+
while read -r reference; do
|
|
258
|
+
if docker manifest inspect "$reference" >/dev/null 2>&1; then
|
|
259
|
+
echo "present: $reference"
|
|
260
|
+
continue
|
|
261
|
+
fi
|
|
262
|
+
echo "missing, building: $reference"
|
|
263
|
+
.venv/bin/rosotacom image build --project "$project" --reference "$reference"
|
|
264
|
+
docker push "$reference" || echo "::warning::could not push $reference"
|
|
265
|
+
done < references.txt
|
|
266
|
+
|
|
267
|
+
# Report the repository only when every reference resolves. A
|
|
268
|
+
# read-only GITHUB_TOKEN (a fork PR, Dependabot) can log in and pull
|
|
269
|
+
# but not push, and the slices must then build as they always did
|
|
270
|
+
# rather than fail on a pull that was never going to work. Probed
|
|
271
|
+
# rather than predicted from the event, so it stays right when
|
|
272
|
+
# GitHub's token rules change.
|
|
273
|
+
available=true
|
|
274
|
+
while read -r reference; do
|
|
275
|
+
docker manifest inspect "$reference" >/dev/null 2>&1 || available=false
|
|
276
|
+
done < references.txt
|
|
277
|
+
|
|
278
|
+
if [[ "$available" == "true" ]]; then
|
|
279
|
+
echo "repository=$repository" >> "$GITHUB_OUTPUT"
|
|
280
|
+
else
|
|
281
|
+
echo "repository=" >> "$GITHUB_OUTPUT"
|
|
282
|
+
echo "::warning::published images unavailable; each e2e slice will build its own"
|
|
283
|
+
fi
|
|
284
|
+
|
|
195
285
|
e2e:
|
|
196
286
|
# One matrix job, not six near-identical copies. The copies were how
|
|
197
287
|
# `e2e-media` ended up listed in ci-success's `needs` with no check on its
|
|
@@ -210,8 +300,11 @@ jobs:
|
|
|
210
300
|
name: e2e-${{ matrix.slice }}
|
|
211
301
|
runs-on: ubuntu-latest
|
|
212
302
|
timeout-minutes: 90
|
|
213
|
-
needs: preflight-success
|
|
214
|
-
if: always() && !cancelled() && needs.preflight-success.result == 'success'
|
|
303
|
+
needs: [preflight-success, image]
|
|
304
|
+
if: always() && !cancelled() && needs.preflight-success.result == 'success' && needs.image.result == 'success'
|
|
305
|
+
permissions:
|
|
306
|
+
contents: read
|
|
307
|
+
packages: read
|
|
215
308
|
strategy:
|
|
216
309
|
fail-fast: false
|
|
217
310
|
matrix:
|
|
@@ -240,7 +333,18 @@ jobs:
|
|
|
240
333
|
- name: Show Docker environment
|
|
241
334
|
run: docker info
|
|
242
335
|
|
|
336
|
+
- name: Log in to GHCR
|
|
337
|
+
if: needs.image.outputs.repository != ''
|
|
338
|
+
run: echo '${{ secrets.GITHUB_TOKEN }}' | docker login ghcr.io -u '${{ github.actor }}' --password-stdin
|
|
339
|
+
|
|
243
340
|
- name: Run E2E slice
|
|
341
|
+
env:
|
|
342
|
+
# Empty when the `image` job could not publish, and then rosotacom
|
|
343
|
+
# builds exactly as before. Set, and each image build becomes a pull
|
|
344
|
+
# of the tag this tree's own build inputs hash to — rosotacom derives
|
|
345
|
+
# that tag itself and never accepts one, so it cannot be pointed at an
|
|
346
|
+
# image built from something else.
|
|
347
|
+
ROSOTACOM_IMAGE_CACHE: ${{ needs.image.outputs.repository }}
|
|
244
348
|
run: just test-e2e-slice ${{ matrix.slice }}
|
|
245
349
|
|
|
246
350
|
- name: Upload session artifacts
|
|
@@ -261,6 +365,7 @@ jobs:
|
|
|
261
365
|
- merge-lightweight
|
|
262
366
|
- package
|
|
263
367
|
- preflight-success
|
|
368
|
+
- image
|
|
264
369
|
- e2e
|
|
265
370
|
if: always() && (github.event_name != 'pull_request' || github.event.pull_request.draft == false)
|
|
266
371
|
|
|
@@ -291,6 +396,10 @@ jobs:
|
|
|
291
396
|
echo "preflight-success failed or was skipped: ${{ needs.preflight-success.result }}"
|
|
292
397
|
exit 1
|
|
293
398
|
fi
|
|
399
|
+
if [[ "${{ needs.image.result }}" != "success" ]]; then
|
|
400
|
+
echo "image failed or was skipped: ${{ needs.image.result }}"
|
|
401
|
+
exit 1
|
|
402
|
+
fi
|
|
294
403
|
if [[ "${{ needs.e2e.result }}" != "success" ]]; then
|
|
295
404
|
echo "one or more e2e slices failed or were skipped: ${{ needs.e2e.result }}"
|
|
296
405
|
exit 1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev23
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -27,7 +27,7 @@ Requires-Dist: argcomplete<4,>=3.6
|
|
|
27
27
|
Requires-Dist: mcap<2,>=1.4
|
|
28
28
|
Requires-Dist: Pillow<13,>=10
|
|
29
29
|
Requires-Dist: PyYAML>=6
|
|
30
|
-
Requires-Dist: ros2docker<0.2,>=0.1.
|
|
30
|
+
Requires-Dist: ros2docker<0.2,>=0.1.5.dev8
|
|
31
31
|
Provides-Extra: dev
|
|
32
32
|
Requires-Dist: build>=1.2; extra == "dev"
|
|
33
33
|
Requires-Dist: check-wheel-contents>=0.6; extra == "dev"
|
|
@@ -244,6 +244,32 @@ example to bake `com_msgs` into its own container image. Ask for the resource by
|
|
|
244
244
|
name rather than reconstructing a path: the names are part of the CLI contract,
|
|
245
245
|
the layout behind them is not.
|
|
246
246
|
|
|
247
|
+
### Reusing an image instead of rebuilding it
|
|
248
|
+
|
|
249
|
+
Somewhere that starts many rosotacom sessions from the same tree — CI above all
|
|
250
|
+
— can build each image once, publish it, and have every later run pull it:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# What this project's images are called: <repository>:<hash of the build inputs>
|
|
254
|
+
rosotacom image references --repository ghcr.io/owner/rosotacom-e2e
|
|
255
|
+
|
|
256
|
+
# Build the one a reference names, then push it
|
|
257
|
+
rosotacom image build --reference ghcr.io/owner/rosotacom-e2e:<hash>
|
|
258
|
+
docker push ghcr.io/owner/rosotacom-e2e:<hash>
|
|
259
|
+
|
|
260
|
+
# Adopt published images anywhere rosotacom would otherwise build
|
|
261
|
+
export ROSOTACOM_IMAGE_CACHE=ghcr.io/owner/rosotacom-e2e
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The tag is a hash of everything that decides the image — base image and its
|
|
265
|
+
pinned digest, apt and pip packages, the Dockerfile and entrypoint ros2docker
|
|
266
|
+
stages, the build UID — so a build-input change is a different tag and a
|
|
267
|
+
published image can never be stale for the tree that adopts it. Nothing accepts
|
|
268
|
+
a reference: rosotacom derives the one its own inputs allow and pulls exactly
|
|
269
|
+
that, and fails rather than quietly rebuilding if it is not there. With
|
|
270
|
+
`ROSOTACOM_IMAGE_CACHE` unset, nothing changes. See
|
|
271
|
+
[docs/ci.md](docs/ci.md) for how the merge gate uses this.
|
|
272
|
+
|
|
247
273
|
See the [example project README](src/rosotacom/resources/examples/README.md)
|
|
248
274
|
for the copyable example layout, the
|
|
249
275
|
[session configuration reference](session-configuration.md) for the session
|
|
@@ -199,6 +199,32 @@ example to bake `com_msgs` into its own container image. Ask for the resource by
|
|
|
199
199
|
name rather than reconstructing a path: the names are part of the CLI contract,
|
|
200
200
|
the layout behind them is not.
|
|
201
201
|
|
|
202
|
+
### Reusing an image instead of rebuilding it
|
|
203
|
+
|
|
204
|
+
Somewhere that starts many rosotacom sessions from the same tree — CI above all
|
|
205
|
+
— can build each image once, publish it, and have every later run pull it:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# What this project's images are called: <repository>:<hash of the build inputs>
|
|
209
|
+
rosotacom image references --repository ghcr.io/owner/rosotacom-e2e
|
|
210
|
+
|
|
211
|
+
# Build the one a reference names, then push it
|
|
212
|
+
rosotacom image build --reference ghcr.io/owner/rosotacom-e2e:<hash>
|
|
213
|
+
docker push ghcr.io/owner/rosotacom-e2e:<hash>
|
|
214
|
+
|
|
215
|
+
# Adopt published images anywhere rosotacom would otherwise build
|
|
216
|
+
export ROSOTACOM_IMAGE_CACHE=ghcr.io/owner/rosotacom-e2e
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The tag is a hash of everything that decides the image — base image and its
|
|
220
|
+
pinned digest, apt and pip packages, the Dockerfile and entrypoint ros2docker
|
|
221
|
+
stages, the build UID — so a build-input change is a different tag and a
|
|
222
|
+
published image can never be stale for the tree that adopts it. Nothing accepts
|
|
223
|
+
a reference: rosotacom derives the one its own inputs allow and pulls exactly
|
|
224
|
+
that, and fails rather than quietly rebuilding if it is not there. With
|
|
225
|
+
`ROSOTACOM_IMAGE_CACHE` unset, nothing changes. See
|
|
226
|
+
[docs/ci.md](docs/ci.md) for how the merge gate uses this.
|
|
227
|
+
|
|
202
228
|
See the [example project README](src/rosotacom/resources/examples/README.md)
|
|
203
229
|
for the copyable example layout, the
|
|
204
230
|
[session configuration reference](session-configuration.md) for the session
|
|
@@ -83,6 +83,63 @@ config, catmux pane logs, Docker logs when available, and the smoke verification
|
|
|
83
83
|
log under `session-instances/`; collect that directory as the first debugging
|
|
84
84
|
artifact when an E2E job fails.
|
|
85
85
|
|
|
86
|
+
### The e2e image is published once, not rebuilt per job
|
|
87
|
+
|
|
88
|
+
Every e2e job used to build the project image from scratch. #236 measured that
|
|
89
|
+
at 154s per job — 57s pulling the multi-GB ROS base from Docker Hub, 40s
|
|
90
|
+
exporting layers, 47s of apt and pip — which at thirteen slices is 33 minutes of
|
|
91
|
+
runner time and thirteen Hub pulls on the critical path of every merge gate.
|
|
92
|
+
|
|
93
|
+
The `image` job now publishes those images to
|
|
94
|
+
`ghcr.io/<owner>/rosotacom-e2e` and each slice pulls instead of building. GHCR
|
|
95
|
+
is co-located with the runners and has no Hub rate limit, so this is one
|
|
96
|
+
transfer where there used to be a transfer plus a build. Measured on run
|
|
97
|
+
31678648935: **154s → 70s per job**, and the slowest slice's pytest run fell
|
|
98
|
+
from 8m19s to 6m50s.
|
|
99
|
+
|
|
100
|
+
The tag is the whole safety argument. It is a SHA-256 of everything that decides
|
|
101
|
+
what the image contains — the `docker build` command ros2docker renders from a
|
|
102
|
+
config (base image and its pinned digest, `APT_PACKAGES`, `PIP_PACKAGES`, the
|
|
103
|
+
build UID) and every file in the context it stages (Dockerfile, entrypoint, any
|
|
104
|
+
baked packages). Change any of them and the name changes, so "the published
|
|
105
|
+
image is stale" is not a state this can reach, which is the objection #226
|
|
106
|
+
raised against caching the image inline.
|
|
107
|
+
|
|
108
|
+
Nothing ever *accepts* a reference. `rosotacom image references` derives them;
|
|
109
|
+
the publisher builds and pushes only what is missing, and only under the name
|
|
110
|
+
its own inputs hash to (`rosotacom image build --reference`). A consumer is told
|
|
111
|
+
a repository, in `ROSOTACOM_IMAGE_CACHE`, and derives the tag itself:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# What this project's build inputs are called
|
|
115
|
+
rosotacom image references --repository ghcr.io/owner/rosotacom-e2e
|
|
116
|
+
|
|
117
|
+
# Adopt them instead of building, anywhere rosotacom would build
|
|
118
|
+
ROSOTACOM_IMAGE_CACHE=ghcr.io/owner/rosotacom-e2e just test-e2e-slice heartbeat
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
With the variable unset, nothing changes: rosotacom builds as it always did. Set
|
|
122
|
+
and the image absent, the job fails rather than falling back — a miss means the
|
|
123
|
+
publisher did not run or did not agree with this tree, and a silent rebuild
|
|
124
|
+
would hide both while costing exactly what this removes. The one place that
|
|
125
|
+
decision is made is the `image` job, which reports its repository only after
|
|
126
|
+
confirming every reference resolves; a read-only `GITHUB_TOKEN` (a fork PR,
|
|
127
|
+
Dependabot) therefore leaves the slices building as before.
|
|
128
|
+
|
|
129
|
+
Two properties are worth keeping in mind when changing this:
|
|
130
|
+
|
|
131
|
+
- **Publisher and consumer read one list.** `2_native_chatter` builds a second
|
|
132
|
+
image from a different package list, so `rosotacom image references` walks the
|
|
133
|
+
project config *and* every scenario application. Publishing only the project
|
|
134
|
+
image would leave that slice adopting something nobody published.
|
|
135
|
+
- **The release and nightly lanes still build from scratch**, as does the
|
|
136
|
+
nightly `image-scan`. That is deliberate: they are what would notice if a
|
|
137
|
+
published image and a fresh build ever stopped agreeing.
|
|
138
|
+
|
|
139
|
+
Content-addressed tags accumulate in the GHCR package — one per distinct set of
|
|
140
|
+
build inputs, so roughly one per change to the base digest or package lists.
|
|
141
|
+
Nothing prunes them yet.
|
|
142
|
+
|
|
86
143
|
### Balancing the e2e slices
|
|
87
144
|
|
|
88
145
|
A slice is not its own pytest invocation. `just test-e2e-slice <name>` runs the
|
|
@@ -102,18 +159,24 @@ with a usage error, and a test owned twice fails
|
|
|
102
159
|
|
|
103
160
|
The costs are warm pytest `call` durations — medians over seven merge-gate runs
|
|
104
161
|
of 2026-08-11/12. On top of them each job pays a fixed
|
|
105
|
-
`RUNNER_SETUP_SECONDS + IMAGE_BUILD_SECONDS` (
|
|
106
|
-
project image
|
|
107
|
-
per job and not per test, balancing warm costs balances wall clock.
|
|
162
|
+
`RUNNER_SETUP_SECONDS + IMAGE_BUILD_SECONDS` (2m05s: 55s of runner setup, then
|
|
163
|
+
the project image obtained inside whichever test runs first). Because that
|
|
164
|
+
constant is per job and not per test, balancing warm costs balances wall clock.
|
|
165
|
+
|
|
166
|
+
`IMAGE_BUILD_SECONDS` models the merge gate, where that image is pulled rather
|
|
167
|
+
than built (see above); the release and nightly lanes still build and pay the
|
|
168
|
+
older 154s. One slice does not currently reproduce its recorded split: `media`
|
|
169
|
+
spends about 24s more than its two costs predict, and it is the critical path,
|
|
170
|
+
so it is the first thing to remeasure.
|
|
108
171
|
|
|
109
172
|
### How many slices
|
|
110
173
|
|
|
111
174
|
`floor_seconds()` is `fixed + slowest single test` — the fastest any partition
|
|
112
175
|
of this suite could be, because one job has to run that test and pays the fixed
|
|
113
|
-
cost like every other. It is currently **
|
|
114
|
-
|
|
176
|
+
cost like every other. It is currently **6m32s**, of which 1m10s is the image
|
|
177
|
+
(7m56s before #236 published it instead of rebuilding it per job).
|
|
115
178
|
|
|
116
|
-
Thirteen slices sit at
|
|
179
|
+
Thirteen slices sit at 7m14s, 1.11x the floor. That is the point of choosing N
|
|
117
180
|
from the numbers rather than from taste: six balanced slices were 13m37s,
|
|
118
181
|
twelve reach the floor, and past twelve every extra job is pure cost. The
|
|
119
182
|
contract test asserts distance to the floor rather than the spread between
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ros2docker==0.1.5.dev8
|
|
@@ -55,6 +55,15 @@ from .deployment import (
|
|
|
55
55
|
parse_assignments,
|
|
56
56
|
resolve_peer_bindings,
|
|
57
57
|
)
|
|
58
|
+
from .image_cache import (
|
|
59
|
+
IMAGE_CACHE_ENV,
|
|
60
|
+
ImageCacheError,
|
|
61
|
+
adopt_cached_image,
|
|
62
|
+
cache_repository,
|
|
63
|
+
cached_reference,
|
|
64
|
+
image_fingerprint,
|
|
65
|
+
reference_tag,
|
|
66
|
+
)
|
|
58
67
|
|
|
59
68
|
anonymize_lib = importlib.import_module("rosotacom.anonymize")
|
|
60
69
|
|
|
@@ -597,6 +606,53 @@ def _scoped_image_name_from_base(base: str, suffix: str) -> str:
|
|
|
597
606
|
return f"{base}-{suffix}"
|
|
598
607
|
|
|
599
608
|
|
|
609
|
+
def _build_image(config_file: Path, override: Mapping[str, object]) -> None:
|
|
610
|
+
"""Build the image these inputs describe, or adopt the published one.
|
|
611
|
+
|
|
612
|
+
With ``ROSOTACOM_IMAGE_CACHE`` unset this is exactly ``ros2docker build``.
|
|
613
|
+
With it set, the build is replaced by a pull of ``<repository>:<hash of
|
|
614
|
+
these build inputs>`` — see `rosotacom.image_cache` for why that name is
|
|
615
|
+
the whole safety argument.
|
|
616
|
+
|
|
617
|
+
The fingerprint deliberately ignores ``override``: it carries the container
|
|
618
|
+
name, the scoped image name, and sometimes isolated-network run args, none
|
|
619
|
+
of which reach ``docker build``. Feeding them in would give the same image
|
|
620
|
+
a different name per session.
|
|
621
|
+
"""
|
|
622
|
+
repository = cache_repository()
|
|
623
|
+
if repository is None:
|
|
624
|
+
ros2docker_build(config_file=config_file, override=override)
|
|
625
|
+
return
|
|
626
|
+
|
|
627
|
+
image_name = str(override["image_name"])
|
|
628
|
+
reference = cached_reference(repository, image_fingerprint(config_file))
|
|
629
|
+
print(f"Adopting published image {reference} as {image_name} (build skipped)")
|
|
630
|
+
adopt_cached_image(reference, image_name)
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
def _project_build_inputs(runtime: RuntimeConfig) -> list[tuple[str, Path]]:
|
|
634
|
+
"""Every ``(label, ros2docker config)`` this project can build an image from.
|
|
635
|
+
|
|
636
|
+
The project image is one of several: each scenario application names its own
|
|
637
|
+
config, and `2_native_chatter` builds a second image from a different
|
|
638
|
+
package list. Publishing only the project image would leave the adopt path
|
|
639
|
+
strict about an image nobody published, so the publisher and the consumer
|
|
640
|
+
read the same list.
|
|
641
|
+
"""
|
|
642
|
+
inputs: list[tuple[str, Path]] = [("project", runtime.ros2docker_config)]
|
|
643
|
+
seen = {runtime.ros2docker_config.resolve()}
|
|
644
|
+
for scenario_name in _scenario_names(runtime):
|
|
645
|
+
definition = _load_scenario_definition(_resolve_scenario(scenario_name, runtime))
|
|
646
|
+
for identity, applications in sorted(definition.applications.items()):
|
|
647
|
+
for application in applications:
|
|
648
|
+
config = application.ros2docker_config.resolve()
|
|
649
|
+
if config in seen:
|
|
650
|
+
continue
|
|
651
|
+
seen.add(config)
|
|
652
|
+
inputs.append((f"{scenario_name}/{identity}/{application.name}", config))
|
|
653
|
+
return inputs
|
|
654
|
+
|
|
655
|
+
|
|
600
656
|
def _instance_name_token(instance_id: str) -> str:
|
|
601
657
|
# Underscore-free so the instance component of a container name can be split
|
|
602
658
|
# off unambiguously (the surrounding name parts are underscore-separated).
|
|
@@ -4911,7 +4967,7 @@ def start_session(args: argparse.Namespace) -> str:
|
|
|
4911
4967
|
|
|
4912
4968
|
common_override = {"container_name": container_name, "image_name": image_name}
|
|
4913
4969
|
if mode == "detached":
|
|
4914
|
-
|
|
4970
|
+
_build_image(runtime.ros2docker_config, common_override)
|
|
4915
4971
|
ros2docker_run(
|
|
4916
4972
|
config_file=runtime.ros2docker_config,
|
|
4917
4973
|
override={**common_override, "run_type": "up", **run_override},
|
|
@@ -4926,7 +4982,7 @@ def start_session(args: argparse.Namespace) -> str:
|
|
|
4926
4982
|
)
|
|
4927
4983
|
_write_docker_log(container_name, instance, identity)
|
|
4928
4984
|
else:
|
|
4929
|
-
|
|
4985
|
+
_build_image(runtime.ros2docker_config, common_override)
|
|
4930
4986
|
ros2docker_run(
|
|
4931
4987
|
config_file=runtime.ros2docker_config,
|
|
4932
4988
|
override={
|
|
@@ -5258,7 +5314,7 @@ def run_scenario_application(args: argparse.Namespace) -> int:
|
|
|
5258
5314
|
network_name,
|
|
5259
5315
|
getattr(args, "network_ip", None),
|
|
5260
5316
|
)
|
|
5261
|
-
|
|
5317
|
+
_build_image(application.ros2docker_config, override)
|
|
5262
5318
|
ros2docker_run(config_file=application.ros2docker_config, override=override)
|
|
5263
5319
|
return 0
|
|
5264
5320
|
|
|
@@ -5332,6 +5388,55 @@ def examples_create_command(args: argparse.Namespace) -> int:
|
|
|
5332
5388
|
return 0
|
|
5333
5389
|
|
|
5334
5390
|
|
|
5391
|
+
def image_references_command(args: argparse.Namespace) -> int:
|
|
5392
|
+
"""Print the content-addressed reference of every image this project builds.
|
|
5393
|
+
|
|
5394
|
+
The publisher's whole job is this list: build and push what is missing. It
|
|
5395
|
+
never chooses a tag, so it cannot publish an image under a name that
|
|
5396
|
+
describes different inputs.
|
|
5397
|
+
"""
|
|
5398
|
+
_require_ros2docker()
|
|
5399
|
+
runtime = _load_runtime_config(args)
|
|
5400
|
+
repository = args.repository or cache_repository()
|
|
5401
|
+
if not repository:
|
|
5402
|
+
raise RuntimeError(f"Pass --repository or set {IMAGE_CACHE_ENV} to the repository that holds published images.")
|
|
5403
|
+
|
|
5404
|
+
printed: set[str] = set()
|
|
5405
|
+
for _label, config in _project_build_inputs(runtime):
|
|
5406
|
+
reference = cached_reference(repository, image_fingerprint(config))
|
|
5407
|
+
# Two scenario applications with the same build inputs are one image.
|
|
5408
|
+
if reference in printed:
|
|
5409
|
+
continue
|
|
5410
|
+
printed.add(reference)
|
|
5411
|
+
print(reference)
|
|
5412
|
+
return 0
|
|
5413
|
+
|
|
5414
|
+
|
|
5415
|
+
def image_build_command(args: argparse.Namespace) -> int:
|
|
5416
|
+
"""Build the image whose build inputs hash to the tag in ``--reference``.
|
|
5417
|
+
|
|
5418
|
+
Taking a reference rather than a config keeps the publisher honest: the only
|
|
5419
|
+
thing it can push is an image whose inputs actually hash to the name it is
|
|
5420
|
+
pushing under.
|
|
5421
|
+
"""
|
|
5422
|
+
_require_ros2docker()
|
|
5423
|
+
runtime = _load_runtime_config(args)
|
|
5424
|
+
reference = args.reference
|
|
5425
|
+
wanted = reference_tag(reference)
|
|
5426
|
+
|
|
5427
|
+
for label, config in _project_build_inputs(runtime):
|
|
5428
|
+
if image_fingerprint(config) != wanted:
|
|
5429
|
+
continue
|
|
5430
|
+
print(f"Building {label} ({config}) as {reference}")
|
|
5431
|
+
ros2docker_build(config_file=config, override={"image_name": reference})
|
|
5432
|
+
return 0
|
|
5433
|
+
|
|
5434
|
+
raise ImageCacheError(
|
|
5435
|
+
f"No image this project builds has the fingerprint {wanted}. Take the reference from "
|
|
5436
|
+
f"`rosotacom image references`; it changes whenever the build inputs do."
|
|
5437
|
+
)
|
|
5438
|
+
|
|
5439
|
+
|
|
5335
5440
|
def resources_path_command(args: argparse.Namespace) -> int:
|
|
5336
5441
|
"""Print the host path of a packaged resource, for external tooling."""
|
|
5337
5442
|
|
|
@@ -8648,6 +8753,7 @@ TOP_LEVEL_COMMANDS = {
|
|
|
8648
8753
|
"list-sessions",
|
|
8649
8754
|
"scenario",
|
|
8650
8755
|
"examples",
|
|
8756
|
+
"image",
|
|
8651
8757
|
"resources",
|
|
8652
8758
|
"config",
|
|
8653
8759
|
"bundle",
|
|
@@ -9376,6 +9482,30 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
9376
9482
|
examples_create_parser.add_argument("--force", action="store_true", help="Replace the target if it exists.")
|
|
9377
9483
|
examples_create_parser.set_defaults(func=examples_create_command)
|
|
9378
9484
|
|
|
9485
|
+
image_parser = subparsers.add_parser("image", help="Publish and consume the project's container images.")
|
|
9486
|
+
image_subparsers = image_parser.add_subparsers(dest="image_action", required=True)
|
|
9487
|
+
|
|
9488
|
+
image_references_parser = image_subparsers.add_parser(
|
|
9489
|
+
"references", help="Print the content-addressed reference of every image this project builds."
|
|
9490
|
+
)
|
|
9491
|
+
_add_common_config_args(image_references_parser)
|
|
9492
|
+
image_references_parser.add_argument(
|
|
9493
|
+
"--repository",
|
|
9494
|
+
help=f"Repository holding published images, e.g. ghcr.io/owner/name. Defaults to {IMAGE_CACHE_ENV}.",
|
|
9495
|
+
)
|
|
9496
|
+
image_references_parser.set_defaults(func=image_references_command)
|
|
9497
|
+
|
|
9498
|
+
image_build_parser = image_subparsers.add_parser(
|
|
9499
|
+
"build", help="Build the image whose build inputs hash to the tag in --reference."
|
|
9500
|
+
)
|
|
9501
|
+
_add_common_config_args(image_build_parser)
|
|
9502
|
+
image_build_parser.add_argument(
|
|
9503
|
+
"--reference",
|
|
9504
|
+
required=True,
|
|
9505
|
+
help="Full reference from `rosotacom image references`. Its tag decides which image is built.",
|
|
9506
|
+
)
|
|
9507
|
+
image_build_parser.set_defaults(func=image_build_command)
|
|
9508
|
+
|
|
9379
9509
|
resources_parser = subparsers.add_parser("resources", help="Locate resources packaged with rosotacom.")
|
|
9380
9510
|
resources_subparsers = resources_parser.add_subparsers(dest="resources_action", required=True)
|
|
9381
9511
|
resources_path_parser = resources_subparsers.add_parser("path", help="Print the host path of a packaged resource.")
|