Skip to content

Compose, Quadlet and Kubernetes renderings of the robot topology - #463

Merged
Minipada merged 5 commits into
jazzyfrom
feature/450-compose-quadlet-and-kubernetes-rendering
Sep 1, 2026
Merged

Compose, Quadlet and Kubernetes renderings of the robot topology#463
Minipada merged 5 commits into
jazzyfrom
feature/450-compose-quadlet-and-kubernetes-rendering

Conversation

@Minipada

@Minipada Minipada commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds deploy/robot/: the three-container robot tier (dc-ros, vector, dc-uploader) described three ways — compose.yaml, Podman quadlet/*.container+*.volume+*.network units, and a single Kubernetes kubernetes/robot-pod.yaml Pod — so a site deploys it with whatever it already runs, without the topology becoming three different decisions (docs/adr/0015-split-deployment-topology.md).
  • tools/ci/pre-commit/kubeconform.sh schema-validates the Kubernetes manifest via Podman, wired into .pre-commit-config.yaml.
  • deploy/robot/scripts/verify_kube_play.sh: podman kube play runs the Pod manifest with no cluster and asserts it reaches ready (same dc_bridge reports ready signal tools/release/scripts/verify_published_images.sh already uses).
  • deploy/robot/scripts/verify_network_isolation.sh: plain Podman networks prove the robot tier's routing claim — no internet route, and only outbound robot-to-edge connectivity permitted. Verified locally end-to-end (all three checks pass, cleanup confirmed).
  • New CI job verify-robot-manifests (.github/workflows/ci.yaml) runs both checks on push, against the same published dc-ros/dc-uploader images verify-published-images already exercises.

Unlike tools/e2e/compose.split.yaml (the test rendering, with Postgres/RustFS standing in for reachable Destinations), these renderings are the deployable robot tier for the fleet shape (epic #440 scenario 3): Records go out through the blessed vector Destination type to an edge aggregator, and Files go to edge-local object storage — both placeholder hostnames (edge.site.example), since that edge infrastructure is outside this repository. No new build or publish path — building and shipping still uses Podman, unchanged.

Closes #450

Test plan

  • prek run --files <changed> --skip build-doc — all hooks pass, including the new kubeconform hook
  • kubeconform validates kubernetes/robot-pod.yaml locally (Valid: 1, Invalid: 0, Errors: 0)
  • deploy/robot/scripts/verify_network_isolation.sh run locally end-to-end — all three checks pass, no leftover containers/networks after cleanup
  • deploy/robot/scripts/verify_kube_play.sh — needs the published ghcr.io/minipada/ros2_data_collection/dc-ros/dc-uploader images (private registry, not pullable without CI credentials from this environment); exercised by the new verify-robot-manifests CI job on push
  • CI green (verify-robot-manifests, Formatting (prek), existing jobs unaffected)

🤖 Generated with Claude Code

https://claude.ai/code/session_018bkW24nSMdaGbCJyxhBU23

…obot topology

Adds deploy/robot/, describing the three-container robot tier (dc-ros, vector,
dc-uploader) three ways so a site deploys it with whatever it already runs:
compose.yaml, quadlet/*.container+*.volume+*.network, and
kubernetes/robot-pod.yaml — a single Pod, which is what lets
`podman kube play` run it directly with no cluster.

kubeconform (tools/ci/pre-commit/kubeconform.sh) validates the Kubernetes
manifest, wired into pre-commit. deploy/robot/scripts/verify_kube_play.sh
proves the Pod reaches ready the same way
tools/release/scripts/verify_published_images.sh already does (the
"dc_bridge reports ready" log line). deploy/robot/scripts/verify_network_isolation.sh
proves the routing claim with plain Podman networks: no internet route for
the robot tier, and only outbound robot-to-edge connectivity — a routing-
level proof, not the CNI-enforced one #452 does with kind + NetworkPolicy.
Both run as a new CI job (verify-robot-manifests) against the same published
images verify-published-images already exercises.

Unlike tools/e2e/compose.split.yaml (the *test* rendering, with Postgres/
RustFS standing in for reachable Destinations), these renderings are the
deployable robot tier for the fleet shape (epic #440 scenario 3): Records go
out through the blessed `vector` Destination type to an edge aggregator, and
Files go to edge-local object storage — both placeholder hostnames, since
that edge infrastructure is outside this repository.

No new build or publish path: all three renderings pull the same
ghcr.io/minipada/ros2_data_collection/dc-ros and dc-uploader images
.github/workflows/ci.yaml already builds and pushes.

Closes #450

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.44%. Comparing base (7b4e211) to head (e651885).

Additional details and impacted files
@@            Coverage Diff             @@
##            jazzy     #463      +/-   ##
==========================================
- Coverage   71.46%   71.44%   -0.01%     
==========================================
  Files         124      124              
  Lines        7563     7563              
==========================================
- Hits         5404     5403       -1     
- Misses       2159     2160       +1     
Flag Coverage Δ
cpp-jazzy 71.44% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Adds deploy/robot/docs/{single-robot-quick-setup,containers-single-machine,
fleet-topology}.html: standalone, interactive comparisons of scenario 1
(all-in-one container), the Compose/Quadlet rendering this directory adds
(#450), and the target fleet shape (epic #440 scenario 3). Each calls out
the weaknesses of a direct-to-destination shape versus the fleet tier,
grounded in "A Reference Architecture for Robot Fleets" (security exposure,
no edge buffer, sites that won't allow it on their network).

REUSE.toml annotates them instead of an inline header — a leading comment
before <!DOCTYPE html> risks quirks mode in some engines.

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
build-dc-ros-image/build-dc-uploader-image now build and push a :<sha> ref
on every run, PR included — the same CI-internal-reuse pattern already used
for dc-workspace/dc-e2e — instead of being gated to `push` on jazzy
entirely. That lets verify-published-images/verify-robot-manifests pull and
run the actual image a PR just built, catching a broken image or a broken
robot-manifest rendering before merge instead of only after.

Refs are computed by .github/actions/image-ref, ported from
~/dev/monorepo's action of the same name: it also derives a sluggified
branch ref. Both that branch ref and a fixed :latest tag (the ref a fleet
robot would actually pin to, CLAUDE.md's convention) are pushed only on
`push` to jazzy — mirroring monorepo's own podman-push, which withholds
branch_ref on pull_request the same way. A not-yet-merged PR must never
move either floating ref.

verify_kube_play.sh now accepts DC_ROS_IMAGE/DC_UPLOADER_IMAGE overrides
and substitutes them into a temp copy of kubernetes/robot-pod.yaml before
`podman kube play` — the committed manifest hardcodes :latest, which would
otherwise make verify-robot-manifests test a stale image on every PR
instead of the one that PR just built.

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
The Format job failed on push: codespell's -w autofix rewrote "logicalY"
to "logically" inside deploy/robot/docs/*.html's bundled JS (a pan/zoom
helper's identifier, not a real misspelling), corrupting a delivered,
checksummed Archify artifact that should never be hand- or tool-edited
after delivery. Adds those files to the hook's -S skip list, the same
mechanism already used for other generated/binary content in this repo.

Verified the already-committed diagrams are unaffected (git history never
saw the bad rewrite — only codespell's own scratch checkout in CI did).

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
Both latent, surfaced only now that verify-robot-manifests/
verify-published-images actually run on a PR (previous commit) instead of
being skipped entirely.

deploy/robot/kubernetes/robot-pod.yaml: dc-ros's robot-params volumeMount
combined a hostPath already pointing at the exact file with `subPath:
robot_params.yaml`, which appends that path again — podman tried to open
.../robot_params.yaml/robot_params.yaml and failed ("not a directory").
Verified locally: podman kube play now runs the Pod to Ready end-to-end
(dc-ros, dc-uploader and vector all Up, "dc_bridge reports ready" logged).

tools/release/scripts/verify_published_images.sh and five e2e scripts
(run_split.sh and friends) extracted VECTOR_VERSION with a bare `grep -oP
'version: v...'` across all of ros2_data_collection.repos, which also
matches aws_sdk_vendor's own `version: v1.11.600` line — collapsing into
"0.57.0\n1.11.600" and breaking podman's image ref parsing
("docker.io/timberio/vector:0.57.0\n1.11.600-debian: invalid reference
format"). Scopes the grep to the vector_vendor block (`grep -A3
'vector_vendor:' | grep -oP ...`) in all six places that shared this
pattern, so the apt and container paths agree on one version everywhere,
consistent with the comments already claiming they do.

Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
@Minipada
Minipada merged commit d9340bb into jazzy Sep 1, 2026
14 checks passed
@github-actions
github-actions Bot deleted the feature/450-compose-quadlet-and-kubernetes-rendering branch September 1, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant