Skip to content

ci: deterministic capnp codegen via pinned Docker image + drift check#132

Merged
DZakh merged 7 commits into
mainfrom
claude/adoring-dijkstra-o4A0z
Jun 9, 2026
Merged

ci: deterministic capnp codegen via pinned Docker image + drift check#132
DZakh merged 7 commits into
mainfrom
claude/adoring-dijkstra-o4A0z

Conversation

@DZakh

@DZakh DZakh commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

Refactored generated Cap'n Proto code to use dedicated helper functions from the capnp::introspect module instead of inline panic! macros. This improves code maintainability and consistency across the generated schema bindings.

Key Changes

  • Replaced all panic!("invalid field index {}", index) calls with ::capnp::introspect::panic_invalid_field_index(index)
  • Replaced all panic!("invalid annotation indices ({:?}, {}) ", child_index, index) calls with ::capnp::introspect::panic_invalid_annotation_indices(child_index, index)
  • Updated 30+ occurrences across multiple schema modules (query_response_data, rollback_guard, cached_query_response, selection, block_filter, log_filter, authorization_selection, transaction_filter, trace_filter, field_selection, and others)

Additional Changes

  • Added CI workflow job check_capnp_generated to verify that committed Cap'n Proto generated code stays in sync with the schema
  • Added documentation in hypersync-net-types/Makefile explaining the exact tools and versions required to regenerate the Cap'n Proto code (capnp compiler and capnpc-rust plugin v0.23.2)
  • The CI job will fail if the generated code becomes stale, ensuring developers regenerate it when modifying .capnp schema files

Implementation Details

These changes were generated by the Cap'n Proto code generator (capnpc-rust v0.23.2) and represent a refactoring of the generated code to use more maintainable helper functions rather than inline panic macros. The helper functions provide better error messages and centralized panic handling.

https://claude.ai/code/session_01BFU2E3mDhWx5sg1AQKuQvB

Summary by CodeRabbit

  • Chores
    • CI now includes an automated check that fails if generated bindings are out of date.
    • Code generation was moved to a containerized workflow for reproducible, environment-independent outputs.
    • Added a configurable, pinned codegen image and tooling to ensure deterministic generation and consistent formatting of produced bindings.

Add a check_capnp_generated job that regenerates the committed capnp code and
fails if it drifted from the schema (the build no longer regenerates it). The
capnpc-rust plugin is pinned to the exact version (=0.23.2, matching the capnp
runtime) because the generated bytes depend on the plugin version and a
floating range would yield spurious diffs.

Regenerate hypersync_net_types_capnp.rs with capnpc 0.23.2 so the committed
code matches the pinned plugin; the previous file predated the 0.23 codegen
(panic! helper calls). Document the required toolchain in the Makefile.

Co-authored-by: claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Dockerized Cap'n Proto Rust codegen (Dockerfile + Makefile), a .dockerignore limiting the build context, and a CI job that runs the Make target and fails if regenerated hypersync-net-types/src/__generated__ differs from committed files.

Changes

Cap'n Proto Generated Code Validation

Layer / File(s) Summary
Cap'n Proto codegen Dockerfile
hypersync-net-types/capnp-codegen.Dockerfile, hypersync-net-types/.dockerignore
New Dockerfile pins Rust toolchain, installs capnproto, rustfmt, and a specific capnpc version, compiles hypersync_net_types.capnp, formats the generated Rust, and exports only the generated output; .dockerignore restricts build context to the schema.
Makefile Dockerized generate_capnp_types
hypersync-net-types/Makefile
generate_capnp_types now builds capnp-codegen.Dockerfile using BuildKit and exports generated sources to src/__generated__ instead of running host capnp compile and rustfmt.
Generated code validation job
.github/workflows/ci.yaml
New check_capnp_generated CI job runs make -C hypersync-net-types generate_capnp_types and fails if hypersync-net-types/src/__generated__ differs from regenerated output using git diff --exit-code.
sequenceDiagram
  participant GitHubActions
  participant Makefile
  participant DockerBuild
  participant DockerContainer
  GitHubActions->>Makefile: make -C hypersync-net-types generate_capnp_types
  Makefile->>DockerBuild: docker build (capnp-codegen.Dockerfile)
  DockerBuild->>DockerContainer: run build stage (install capnproto, rustfmt, capnpc)
  DockerContainer->>DockerContainer: capnp compile hypersync_net_types.capnp -> src/__generated__
  DockerContainer->>DockerContainer: rustfmt generated file
  DockerContainer->>Makefile: export generated files to repo via buildkit --output
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: deterministic Cap'n Proto code generation via pinned Docker image and the addition of a drift check CI job.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Co-authored-by: claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/ci.yaml (1)

78-99: ⚡ Quick win

Scope job token permissions explicitly.

This job only reads repo contents; relying on default token permissions is broader than needed. Add a job-level permissions: { contents: read }.

Suggested patch
   check_capnp_generated:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yaml around lines 78 - 99, The CI job
"check_capnp_generated" currently uses default token permissions; scope it down
by adding a job-level permissions entry to only allow repository content read
access. Update the job definition for check_capnp_generated to include
permissions: { contents: read } (so the job still can read the repo for git diff
but cannot perform broader actions), ensuring the permissions block is at the
same indentation level as runs-on and steps in that job.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yaml:
- Around line 87-90: The workflow step named "Install capnp schema compiler"
installs packages without refreshing apt metadata; modify that step to run `sudo
apt-get update` (or `sudo apt-get update -y` if preferred) immediately before
`sudo apt-get install -y capnproto libcapnp-dev` so the apt cache is refreshed
on runners; locate the step by its name string "Install capnp schema compiler"
in the CI job and insert the update command at the top of the step's run block.
- Around line 81-86: Replace the archived actions-rs/toolchain@v1 by using a
maintained Rust setup action (e.g., dtolnay/rust-toolchain or
actions-rust-lang/setup-rust-toolchain) and pin that replacement to a specific
commit SHA; also replace mutable tags for actions/checkout@v3 and
Swatinem/rust-cache@v2 with their respective full commit SHAs so all three uses:
entries are immutable and point to exact commits.

---

Nitpick comments:
In @.github/workflows/ci.yaml:
- Around line 78-99: The CI job "check_capnp_generated" currently uses default
token permissions; scope it down by adding a job-level permissions entry to only
allow repository content read access. Update the job definition for
check_capnp_generated to include permissions: { contents: read } (so the job
still can read the repo for git diff but cannot perform broader actions),
ensuring the permissions block is at the same indentation level as runs-on and
steps in that job.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36d0c9e5-91da-4b4a-af22-001f94e73439

📥 Commits

Reviewing files that changed from the base of the PR and between 164d6ab and 27c569e.

⛔ Files ignored due to path filters (1)
  • hypersync-net-types/src/__generated__/hypersync_net_types_capnp.rs is excluded by !**/__generated__/**
📒 Files selected for processing (2)
  • .github/workflows/ci.yaml
  • hypersync-net-types/Makefile

Comment thread .github/workflows/ci.yaml Outdated
Comment thread .github/workflows/ci.yaml Outdated

@JonoPrest JonoPrest left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem as hyper fuel. Capnp codegen is not fully deterministic depending on which version of capnp you're using. But it's difficult to align these versions on all environments since they don't publish binaries for all platforms. We can always set the make cmd to actually use docker rather than local capnp to get deterministic codegen though

@JasoonS

JasoonS commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

set the make cmd to actually use docker rather than local capnp to get deterministic codegen though

Sounds like a decent idea 👍

Run codegen inside a pinned toolchain image (rust + capnproto + capnpc-rust)
via the Makefile and the check_capnp_generated job, instead of relying on the
host's locally installed capnp/rustfmt. This makes the committed generated code
byte-for-byte reproducible across developer machines and CI, avoiding spurious
diffs from platform/version mismatches.

Co-authored-by: claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/ci.yaml (1)

73-82: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Set least-privilege permissions for check_capnp_generated.

This job currently inherits default token permissions. It only needs read access for checkout/diff, so add an explicit permissions block.

Suggested patch
   check_capnp_generated:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
       - uses: actions/checkout@v3
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yaml around lines 73 - 82, The check_capnp_generated
job currently uses default token permissions; update the job named
check_capnp_generated to grant least privilege by adding an explicit permissions
block (e.g., permissions: contents: read) so the workflow only has read access
needed for actions/checkout and running git diff; place the permissions block at
the top level of the job definition near the runs-on line to apply only to this
job and keep the existing steps and commands unchanged.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@hypersync-net-types/capnp-codegen.Dockerfile`:
- Around line 4-11: The Dockerfile uses mutable inputs — the base image tag
`FROM rust:1.94-slim-bookworm` and a floating Debian package install `apt-get
install ... capnproto` — causing nondeterministic builds; fix it by pinning the
base image to a specific digest (replace the `FROM rust:1.94-slim-bookworm` tag
with its immutable sha256 digest) and pinning the capnproto package (install a
specific Debian package version or download and install the exact .deb for
capnproto matching the chosen Debian release), ensure the existing `ARG
CAPNPC_VERSION` is used to align tools with the pinned system package, and
update the RUN step to install the exact package version instead of the
unversioned package name so CI builds are reproducible.

---

Outside diff comments:
In @.github/workflows/ci.yaml:
- Around line 73-82: The check_capnp_generated job currently uses default token
permissions; update the job named check_capnp_generated to grant least privilege
by adding an explicit permissions block (e.g., permissions: contents: read) so
the workflow only has read access needed for actions/checkout and running git
diff; place the permissions block at the top level of the job definition near
the runs-on line to apply only to this job and keep the existing steps and
commands unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f197e174-b1e9-4983-baf5-2c6fd27c60f1

📥 Commits

Reviewing files that changed from the base of the PR and between b502e29 and fe599f7.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • hypersync-net-types/Makefile
  • hypersync-net-types/capnp-codegen.Dockerfile

Comment thread hypersync-net-types/capnp-codegen.Dockerfile Outdated
Pin the Docker base image to an immutable digest so the codegen toolchain
(notably rustfmt) can't drift when the rust:1.94-slim-bookworm tag moves,
keeping the generated output fully reproducible.

Co-authored-by: claude <noreply@anthropic.com>
@DZakh DZakh changed the title Replace panic! calls with capnp introspect helper functions ci: deterministic capnp codegen via pinned Docker image + drift check Jun 9, 2026
Comment thread hypersync-net-types/capnp-codegen.Dockerfile
DZakh and others added 2 commits June 9, 2026 11:50
Collapse the Makefile target into a single `docker build --output` that runs
codegen inside the image and exports the generated file directly, dropping the
separate `docker run`, the volume mount and UID/GID mapping. A .dockerignore
keeps the build context to just the schema.

Move the codegen base to Debian trixie so the capnp compiler is 1.1.0 (>=1.0)
instead of bookworm's 0.9.2, and pin both the base image digest and the
capnproto apt version since the compiler version affects the generated schema
blobs. Regenerate the committed code accordingly.

Co-authored-by: claude <noreply@anthropic.com>
Add a top-level `permissions: contents: read` block since every CI job is
read-only, and document the .dockerignore schema-only build context.

Co-authored-by: claude <noreply@anthropic.com>

@JonoPrest JonoPrest left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it 👍🏼

Also realised capnpc was not previously aligned with the version we were using in cargo.toml (0.23)

This might be worth adding a CI test to make sure that the versions in dockerfile and cargo.tomls match

Add a step to check_capnp_generated that fails if the capnpc version pinned in
capnp-codegen.Dockerfile drifts from any `capnp` dependency in the workspace
Cargo.toml files. The codegen plugin and the runtime are released in lockstep,
so they must stay aligned.

Co-authored-by: claude <noreply@anthropic.com>
@DZakh DZakh merged commit 913a6f1 into main Jun 9, 2026
7 checks passed
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.

3 participants