Skip to content

build(anycable): install anycable-go only in the API images - #4083

Open
EmilyRagan wants to merge 3 commits into
mainfrom
anycable-api-images-only
Open

EmilyRagan wants to merge 3 commits into
mainfrom
anycable-api-images-only

Conversation

@EmilyRagan

@EmilyRagan EmilyRagan commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Move the anycable-go binaries out of openc3-ruby and into a new openc3-anycable/ directory, and install them only in the two images that run them: openc3-cosmos-cmd-tlm-api and openc3-cosmos-script-runner-api.

  • openc3-ruby/Dockerfile and Dockerfile-ubi no longer copy or install anycable-go.
  • The API Dockerfiles install the binary that matches the build architecture with RUN --mount=type=bind,from=anycable, so the unused architecture never lands in an image layer.
  • The anycable build context is passed in compose-build.yaml (additional_contexts), scripts/release/build_multi_arch.sh and scripts/linux/openc3_build_ubi.sh.
  • The build-cosmos CI action hashes openc3-anycable into both API image cache keys, so a binary update rebuilds them.
  • build-anycable.sh, the update-anycable skill and the package audit now point at openc3-anycable/. The audit checks anycable-go in both API images.

Why it changed

Only the two API images start anycable-go (see their Procfiles), but openc3-ruby copied both the amd64 and arm64 binaries (~76 MB) into every image built on it: base, node, operator, init and the APIs. The unused architecture and the unused binary stayed in the image layers.

CVEs found and reported on go, impacting anycable-go, previously flowed through to more images of ours than necessary. The following images did contain these binaries and did fail on Trivy scans when new go CVEs were discovered that now do not: openc3-ruby, openc3-base, openc3-node, openc3-operator, openc3-cosmos-init, openc3-enterprise-gem, openc3-enterprise-metrics, openc3-enterprise-operator, and openc3-cosmos-enterprise-init. Only the images that actually use these binaries should contain them and be impacted by their CVEs

Testing strategy

Built all relevant images from clean worktrees of main and of this branch, and compared sizes (below). Verified the installed binary runs and reports 1.6.16.1-f8b38bb.

Not tested: the multi-arch release script, scripts/windows/openc3_setup.bat, and running the package audit. The UBI and multi-arch paths rely on --build-context, which podman only supports from 4.8.

Review notes

Measured on an arm64 host, so each image contains the arm64 binary. Sizes are uncompressed (docker image inspect).

Image Before After Change
openc3-ruby 1486.8 MB 1382.8 MB −104.0 MB
openc3-base 2252.6 MB 2148.7 MB −104.0 MB
openc3-node 1722.3 MB 1618.3 MB −104.0 MB
openc3-operator 2252.6 MB 2148.7 MB −104.0 MB
openc3-cosmos-init 2583.7 MB 2479.8 MB −103.9 MB
openc3-cosmos-cmd-tlm-api 2299.0 MB 2245.2 MB −53.8 MB
openc3-cosmos-script-runner-api 2297.4 MB 2243.6 MB −53.8 MB
openc3-enterprise-gem 2584.2 MB 2480.3 MB −104.0 MB
openc3-enterprise-metrics 2947.2 MB 2843.2 MB −104.0 MB
openc3-enterprise-operator 2794.2 MB 2690.3 MB −104.0 MB
openc3-cosmos-enterprise-init 2581.0 MB 2477.0 MB −103.9 MB
openc3-cosmos-enterprise-cmd-tlm-api 2806.0 MB 2752.2 MB −53.8 MB
openc3-cosmos-enterprise-script-runner-api 2805.8 MB 2752.0 MB −53.8 MB
openc3-enterprise-grafana 1924.9 MB 1924.9 MB 0

Compressed (per-layer gzip, roughly what a registry stores), the savings are smaller: about 26 MB for most images and about 13 MB for the two API images.

  • The API images still carry the binary, so they save about half as much as the others.
  • Both API builds use their own directory as the Docker context, so they can't see openc3-anycable/ without an additional context. That is why the context is wired into each build path rather than copying the binaries into each API directory (which would add ~76 MB to git per directory).
  • Enterprise has no anycable-go references of its own. Its API images inherit the binary from the core API images (verified present in both), and the other enterprise images built on core shrink along with their parents. The enterprise rows were built from a clean enterprise main worktree on top of the before/after core images. Enterprise grafana only borrows the frontend from openc3-node in a build stage, so it is unchanged.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • AnyCable is now installed in the command-and-telemetry API and script-runner API images instead of the Ruby image.
    • API images include the appropriate AnyCable binary for ARM64 or AMD64.
    • Release packaging checks now compare AnyCable versions across both API images.

EmilyRagan and others added 3 commits October 16, 2026 09:32
Only cmd-tlm-api and script-runner-api run anycable-go, but openc3-ruby
shipped both architecture binaries (~76 MB) to every derived image.
Move the binaries to openc3-anycable/ and install the matching one via a
bind-mounted build context in the two API Dockerfiles.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Without it a binary update leaves the API image hash unchanged and CI
restores a stale cached image.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Move build-anycable.sh next to the binaries, update the update-anycable
skill paths, and audit anycable-go against both API images since
openc3-ruby no longer contains it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f2dd9c9c-15b2-4d06-8728-d4f4800ff08b
📥 Commits

Reviewing files that changed from the base of the PR and between 3ded1cf and 5971595.

📒 Files selected for processing: 16
  • .claude/skills/update-anycable/SKILL.md
  • .github/actions/build-cosmos/action.yml
  • compose-build.yaml
  • openc3-anycable/anycable-go-linux-amd64
  • openc3-anycable/anycable-go-linux-arm64
  • openc3-anycable/anycable_install.sh
  • openc3-anycable/build-anycable.sh
  • openc3-cosmos-cmd-tlm-api/Dockerfile
  • openc3-cosmos-script-runner-api/Dockerfile
  • openc3-ruby/Dockerfile
  • openc3-ruby/Dockerfile-ubi
  • openc3-ruby/anycable_install.sh
  • scripts/linux/openc3_build_ubi.sh
  • scripts/release/build_multi_arch.sh
  • scripts/release/package_audit.rb
  • scripts/release/package_audit_lib.rb
💤 Files with no reviewable changes: 3
  • openc3-ruby/Dockerfile
  • openc3-ruby/Dockerfile-ubi
  • openc3-ruby/anycable_install.sh

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

AnyCable binaries now reside in openc3-anycable/ and are installed in the command-TLM API and script-runner API images. Build scripts provide the required context, and package auditing checks the API images.

Changes: AnyCable API image integration

Layer / File(s) Summary
Binary location and installer
.claude/skills/update-anycable/SKILL.md, openc3-anycable/*, openc3-ruby/Dockerfile*, openc3-ruby/anycable_install.sh, scripts/release/package_audit_lib.rb
Adds the architecture-selecting installer and stages binaries in openc3-anycable/. Removes AnyCable installation from the Ruby images and updates the related instructions and binary destination.
API image installation and build wiring
compose-build.yaml, .github/actions/build-cosmos/action.yml, scripts/linux/openc3_build_ubi.sh, scripts/release/build_multi_arch.sh, openc3-cosmos-cmd-tlm-api/Dockerfile, openc3-cosmos-script-runner-api/Dockerfile
Provides the anycable build context for both API images. Each API Dockerfile runs the installer from that context.
API image package audit
scripts/release/package_audit.rb, scripts/release/package_audit_lib.rb
Checks the API image containers, reports their AnyCable versions, warns when versions differ, and audits the first image’s version.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Sequence Diagram(s)

sequenceDiagram
  participant DockerBuild
  participant AnyCableBuildContext
  participant ApiDockerfile
  participant anycable_install_sh
  DockerBuild->>AnyCableBuildContext: supplies the anycable context
  ApiDockerfile->>AnyCableBuildContext: mounts context during image build
  ApiDockerfile->>anycable_install_sh: runs the installer
  anycable_install_sh->>ApiDockerfile: copies selected binary to /usr/bin/anycable-go
Loading

Suggested reviewers: jmthomas

Merge Risk: ⚪ Minimal · up to 59715

AnyCable now ships only in the two API images that use it, and every image build path is wired to supply its binaries. No outstanding issues block merging; the untested multi-architecture and Windows paths deserve a normal release check.

Security architecture risk: 🔵 Low · up to 59715

The change limits AnyCable to the images that run it, and the inspected build paths supply the new dependency. A command-injection finding remains in release tooling, but its input source, execution authority, and effective exposure predate this PR. Production rollback behavior and binary contents were not verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The retained injection path requires influence over the version tag supplied to the local audit invocation. Successful injection executes with the audit process's host permissions and any credentials or Docker access available to it. The inspected path does not establish a tenant-facing or network-request route.

Security Findings and Attack Paths

  • observed — The retained command-injection finding is supported by CLI-derived image names interpolated into a shell command. It predates this PR: the base used the same interpolation in check_anycable, and package inventory already passed the same tag into shell commands before that check. The PR changes image selection and invocation count, not the demonstrated execution authority or input boundary.

Trust Boundaries and Controls

  • observed — The installer trusts the supplied build context as executable input. Its source and binary paths are quoted, and the API Dockerfiles supply a fixed mount path. The changed call sites preserve a build-input trust boundary rather than introducing a runtime request-to-root transition.

Resilience and Maintainability Implications

  • observed — The binary updater still writes amd64 and arm64 downloads sequentially into their final paths. Failure of the second download can leave mixed local contents without rollback. This lifecycle limitation already existed at the base; this PR changes the destination directory rather than introducing the non-atomic update.

Hardening Proposals

  • proposed — Use argument-safe process execution for audit commands. Separately, make failed or disagreeing image-version checks explicit audit failures, and stage both architecture downloads before replacing the committed binary pair.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 6 files. (5 skipped: 5 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: installing anycable-go only in the API images.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 6 files. (5 skipped: 5 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 Brakeman (8.0.6)

Brakeman reported 6 analysis error(s); security analysis is incomplete

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.55%. Comparing base (a44037d) to head (5971595).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4083      +/-   ##
==========================================
+ Coverage   80.49%   80.55%   +0.05%     
==========================================
  Files         904      904              
  Lines       68992    68992              
  Branches     2681     2681              
==========================================
+ Hits        55538    55575      +37     
+ Misses      12792    12747      -45     
- Partials      662      670       +8     
Flag Coverage Δ
frontend 67.34% <ø> (+0.03%) ⬆️
python 80.52% <ø> (+0.03%) ⬆️
ruby-api 83.19% <ø> (+0.12%) ⬆️
ruby-backend 86.10% <ø> (+0.06%) ⬆️

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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sonarqubecloud

Copy link
Copy Markdown

@EmilyRagan
EmilyRagan marked this pull request as ready for review October 16, 2026 17:16
@EmilyRagan EmilyRagan self-assigned this Oct 16, 2026

This branch has not been deployed

No deployments
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