Skip to content

feat!: Update dependencies and modernize Rust code patterns - #1

Open
taorepoara wants to merge 21 commits into
masterfrom
claude/update-buildkit-proto-8VpS0
Open

feat!: Update dependencies and modernize Rust code patterns#1
taorepoara wants to merge 21 commits into
masterfrom
claude/update-buildkit-proto-8VpS0

Conversation

@taorepoara

Copy link
Copy Markdown
Member

Summary

This PR modernizes the codebase by updating to newer Rust idioms, removing deprecated dependencies, and updating protobuf definitions to support new BuildKit features.

Key Changes

Dependency Updates

  • Updated buildkit-proto edition from 2018 to 2021
  • Removed deprecated dependencies: libc, mio, pin-project, bytes
  • Replaced custom stdio implementation with hyper_util::rt::TokioIo wrapper
  • Updated tokio runtime configuration from deprecated scheduler syntax to modern flavor parameter

Rust Code Modernization

  • Converted Into trait implementations to From (preferred pattern)
  • Replaced &[T] slice references with array literals in function calls
  • Updated boolean assertions from assert_eq!(x, true) to assert!(x) pattern
  • Removed unnecessary reference dereferencing in pattern matching
  • Added #[allow(clippy::result_unit_err)] and #[allow(clippy::upper_case_acronyms)] attributes where appropriate
  • Changed lifetime bounds from 'a, 'b: 'a to simpler 'b where applicable
  • Updated #[derive(Default)] usage and added #[default] attribute on enum variants
  • Replaced if let Err(_) with .is_err() pattern

Protobuf Updates

  • Added new proto files: google/protobuf/descriptor.proto, google/protobuf/any.proto, google/rpc/status.proto, sourcepolicy/pb/policy.proto, vtproto/ext.proto
  • Extended gateway service with new RPC methods: ReadFileContainer, ReadDirContainer, StatFileContainer
  • Added support for CDI devices in ExecOp and worker records
  • Added git, image, and HTTP source resolution request/response types
  • Updated ResolveSourceMetaRequest with new source type fields
  • Added timestamp import to gateway proto

Build Configuration

  • Updated workspace resolver to version 2
  • Updated BuildKit version from v0.18 to v0.29.0 in update script

I/O Implementation

  • Simplified StdioSocket by removing custom PollEvented wrapper and using tokio's native Stdin/Stdout directly
  • Updated AsyncRead/AsyncWrite implementations to use modern tokio API with ReadBuf
  • Wrapped result in TokioIo for compatibility with tonic transport layer

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc

claude and others added 17 commits April 25, 2026 19:47
Bumps the BUILDKIT_VERSION pinned in update.sh from v0.18 to v0.29.0
and refreshes every .proto file by re-running the script. Also adds
the third-party schemas the script already references (sourcepolicy,
vtprotobuf, google.rpc, google.protobuf), which were missing on disk
and required by the gateway/fsutil imports.

`cargo build -p buildkit-proto` succeeds.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
Adds the new ExecOp.cdi_devices field to the production code path in
ops/exec/command.rs.

Test fixtures in ops/exec/mod.rs and ops/fs/mod.rs were already missing
several fields added in earlier proto upgrades (Mount.tmpfs_opt /
result_id / content_cache, Meta.hostname / cgroup_parent / ulimit /
remove_mount_stubs_recursive / valid_exit_codes, FileActionCopy.required_paths
and friends). They are now closed with `..Default::default()` so future
proto schema additions don't keep breaking the same fixtures.

`cargo build -p buildkit-llb` succeeds.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
- ResolveImageConfigRequest gained resolver_type, session_id, store_id
  and source_policies in v0.18+ — keep existing fields and let prost
  defaults cover the rest via `..Default::default()`.
- ReadFileRequest gained mount_index in v0.29.
- frontend Result gained attestations in v0.18+.

Using `..Default::default()` keeps these literals robust against future
schema additions.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
The frontend Result.result oneof variant `ref = 3` was promoted from
a plain string to a `Ref { id, def }` message. Update the solve
response match (extract `id`) and finish_with_success construction
(wrap output.0 in `Ref { id, def: None }`).

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
The previous v0.18 upgrade swapped tonic_build::compile for
prost_build::compile_protos, which dropped generation of the
LlbBridgeClient gRPC client expected by buildkit-frontend.

Restore tonic-build, bump it to 0.12 (the first line compatible with
prost 0.13.x), add tonic 0.12 as a runtime dep so the generated client
code compiles, and switch the crate to edition 2021 (TryInto in prelude
is required by tonic 0.12 generated code).

Also set workspace.resolver = "2" so the proto crate's edition-2021
features apply consistently across the workspace.

`cargo build -p buildkit-proto` succeeds and the generated module
exposes `moby::buildkit::v1::frontend::llb_bridge_client::LlbBridgeClient`
again.

Note: buildkit-frontend still pins tonic 0.1 + tokio 0.2 + tower 0.3
+ mio 0.6, which are incompatible with tonic 0.12. Bringing
buildkit-frontend forward (tonic / tokio / hyper / tower upgrade and
the stdio.rs mio→AsyncFd rewrite) is a follow-up beyond the proto
update scope.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
The newer `mismatched_lifetime_syntaxes` lint (deny-by-default through
`#![deny(warnings)]`) flagged three sites where an elided lifetime on an
input was paired with a hidden lifetime on a return type. Tighten each
signature to use `'_` consistently so the relationship is explicit.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
After cat 1 regenerated the buildkit-proto gRPC client with tonic 0.12,
buildkit-frontend stayed pinned on tonic 0.1 / tokio 0.2 / tower 0.3,
which caused the `Channel: Service<Request<UnsyncBoxBody<Bytes,
Status>>>` trait bound to fail at every `LlbBridgeClient` call site:
the v0.1 Channel and the v0.12 generated client were incompatible.

Bumps the runtime stack to match buildkit-proto:

  - tonic 0.1 -> 0.12
  - tokio 0.2 -> 1
  - tower 0.3 -> 0.5 (only the `util` feature is needed)
  - drop mio 0.6, pin-project 0.4, libc, bytes (no longer used)
  - add hyper-util 0.1 with the `tokio` feature so we can adapt our
    AsyncRead/Write socket to the hyper::rt::Read/Write that
    Endpoint::connect_with_connector now requires

stdio.rs is rewritten on top of `tokio::io::{stdin, stdout}` (which
became async in tokio 1.x), wrapped in `hyper_util::rt::TokioIo` at the
connector boundary; the custom mio-based `Evented` plumbing is gone.
The tokio runtime macros in the examples switch to the
`flavor = "..."` syntax. An unused `ResolveMode` re-export is removed.

`cargo build --workspace --all-targets` and `cargo test --workspace`
both pass (29 tests).

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
The crates declare `#![deny(clippy::all)]`, and several lints have been
added to clippy since the project was last touched, so `cargo clippy`
failed with 35+ errors. Most were auto-fixable via `cargo clippy --fix`
(idiomatic `From` instead of `Into`, `#[derive(Default)]` instead of a
manual impl, redundant references / patterns, `strip_prefix` over
manual slicing, ...). The rest are mechanical:

  - Drop unused lifetime parameters on impl blocks (`impl<'a> ...` where
    `'a` never appears in the impl signature) in
    `buildkit-llb/src/ops/{exec/command,fs/sequence,source/{git,http,
    image,local}}.rs`.
  - Switch `crate::...` to `$crate::...` inside the exported
    `check_op!` / `check_op_property!` macros so they keep referring to
    `buildkit_llb` when used from doctests / external test crates.
  - Allow `clippy::result_unit_err` on the `FileOperation` trait to
    preserve the public `Result<_, ()>` API.
  - Allow `clippy::upper_case_acronyms` on the `LLB` test enum variant.

`cargo clippy --workspace --all-targets -- -D warnings` and
`cargo test --workspace` both pass clean.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
…atform()

Adds a new `crate::ops::platform` module that re-exports
`buildkit_proto::pb::Platform` together with constructor helpers for the
common targets (`linux_amd64`, `linux_arm64`, `linux_arm_v7`,
`windows_amd64`, ...) and a `platform_id` helper that produces the
canonical `<os>/<arch>[/<variant>]` string used as a key in BuildKit's
RefMap and in the `containerimage.config/<id>` metadata key.

  - `Command::platform(Platform)` populates `pb::Op.platform` on exec
    ops so workers can be scheduled accordingly (cross-compilation).
  - `ImageSource::with_platform(Platform)` does the same on source ops
    and exposes `.platform()` so the frontend bridge can pass the
    constraint through to `ResolveImageConfigRequest.platform`.

Adds a `platform` arm to the internal `check_op_property!` macro and
three new serialization tests (one per builder + a unit test on
`platform_id`). `cargo test -p buildkit-llb` runs 23 tests (was 20).

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
Picks up the platform-aware ops added on the buildkit-llb side and wires
multi-platform support through the bridge end to end:

  - `Bridge::resolve_image_config` now forwards
    `ImageSource::platform()` into `ResolveImageConfigRequest.platform`,
    so per-platform configs are resolved correctly.
  - `Bridge::solve_multi_platform[ _with_cache]` accepts a graph that
    yields a `RefMap` and returns `HashMap<String, OutputRef>` keyed by
    the canonical platform string. Single-ref responses degrade to a
    one-entry map.
  - `FrontendOutput` now has a `with_multi_platform(Vec<MultiPlatformEntry>)`
    constructor alongside the existing single-output ones. Each entry
    pairs a `pb::Platform` with an `OutputRef` and an optional
    `ImageSpecification`; the id defaults to `platform_id(&p)` and can
    be overridden via `with_id()`.
  - `Bridge::finish_with_success` now takes the whole `FrontendOutput`
    and dispatches: single results keep the previous wire format, while
    multi-platform results are encoded as `RefResult::Refs(RefMap)`
    plus a `refs.platforms` metadata blob (matching BuildKit's
    `exptypes.Platforms` JSON shape - capital `ID`, dotted `os.version`
    / `os.features` keys) plus a per-platform
    `containerimage.config/<id>` entry whenever `image_spec` is set.

Adds OCI types in `oci.rs` for callers that need to consume or build a
manifest list directly: `ImageIndex`, `Descriptor`, and an OCI
`Platform` that reuses the existing typed `Architecture` /
`OperatingSystem` enums and round-trips through the dotted
`os.version` / `os.features` JSON keys.

Tests: 13 in buildkit-frontend (was 9): the new ones cover the OCI
index round-trip, the `refs.platforms` JSON shape, and the duplicate /
empty error paths.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
The OCI image-spec has gained a handful of optional fields since v1.0
(`os.version`, `os.features`, `variant`, OCI v1.1 referrers, ...) and
Docker has long shipped its own widely-used config extensions
(`Healthcheck`, `Shell`, `ArgsEscaped`). buildkit-frontend was only
exposing the v1.0 base, so any caller round-tripping an existing image
config silently dropped these fields. This adds them.

Top-level `ImageSpecification`:

  - `os_version: Option<String>`   (JSON `os.version`)
  - `os_features: Option<Vec<String>>`  (JSON `os.features`)
  - `variant: Option<String>`

`ImageConfig` now also carries the Docker extensions, all `Option<_>`
so the existing OCI-only round-trips stay byte-for-byte stable:

  - `healthcheck: Option<Healthcheck>` - new struct mirroring Docker's
    shape, with `Option<Duration>` fields (de)serialized as Go's
    `time.Duration` JSON convention (integer count of nanoseconds).
    Includes the modern `start_interval` field from newer
    Docker/containerd. `Test` covers `["NONE"]`, `["CMD", ...]` and
    `["CMD-SHELL", ...]` shapes.
  - `shell: Option<Vec<String>>` - the default shell used by the
    shell-form of `RUN` / `CMD` / `ENTRYPOINT`.
  - `args_escaped: Option<bool>` - Windows-only, deprecated but still
    emitted by older pipelines so we keep it for fidelity.

`ImageConfig` now also derives `Default`, so callers can pick the
fields they care about with `..Default::default()` instead of having
to spell every `None` (the examples are migrated to that style).

`Architecture` gains `Riscv64`, `Loong64` and `Wasm` to match the
modern Go/OCI list. `OperatingSystem` gains `Aix`, `Android`, `Hurd`,
`Illumos`, `Ios`, `Js` and `Zos`.

OCI v1.1 additions on the descriptor types:

  - `Descriptor.artifact_type: Option<String>`
  - `Descriptor.data: Option<String>` (base64 inline payload)
  - `ImageIndex.subject: Option<Descriptor>` (referrers API)
  - `ImageIndex.artifact_type: Option<String>`
  - new `ImageManifest` struct (per-platform manifest, the type that
    `ImageIndex` entries resolve to) with the same `subject` /
    `artifactType` knobs.

Eight new round-trip tests cover: every Docker-extension field at
once, the dotted top-level keys with all three new optionals,
`Healthcheck::Test = ["NONE"]` minimal case, the new architecture and
OS variants, OCI v1.1 fields on `ImageIndex` and `ImageManifest`, and
the empty `ImageConfig::default()`.

`cargo test --workspace` now runs 44 tests (was 36); `cargo clippy
--workspace --all-targets -- -D warnings` is clean.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
Bumps the BUILDKIT_VERSION pin in update.sh from v0.29.0 to v0.30.0
and re-runs the script. The only schema delta between the two
upstream tags on the five .proto files we vendor is a single new
optional field on api/types/worker.proto:

    message BuildkitVersion {
        string package = 1;
        string version = 2;
        string revision = 3;
        string dockerfileVersion = 4;  // added in v0.30.0
    }

gateway.proto, ops.proto, caps.proto and sourcepolicy.proto are
byte-identical to v0.29.0 in this release, so no Rust source needs
to change: the regenerated `BuildkitVersion` struct just gains a
`dockerfile_version: String` field that callers can read or ignore.

`cargo build --workspace --all-targets` and `cargo test --workspace`
(44 tests: 21 in buildkit-frontend, 23 in buildkit-llb) both pass.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
`impl ToString for Platform` was added in 6cbf078 ("feat: Platform
serialization"). It works, but clippy's `to_string_trait_impl` lint
(now part of `clippy::all`) flags it because the standard library
already ships a blanket `impl<T: Display> ToString for T`. Switch to
`fmt::Display` so we get `to_string()` for free and `cargo clippy
--workspace --all-targets -- -D warnings` is clean.

No behavior change: the formatted strings are byte-for-byte the same,
so existing `platform.to_string()` callers (notably
`buildkit_llb::ops::platform::platform_id`) keep working.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
@taorepoara taorepoara changed the title Update dependencies and modernize Rust code patterns feat!: Update dependencies and modernize Rust code patterns Jun 3, 2026
claude and others added 4 commits June 3, 2026 15:12
buildkit-proto has been on edition 2021 for a while (since the proto
regeneration commits), but the two downstream crates were still
pinned to 2018, which made the workspace a bit awkward: the same
patterns compiled with different rules from one crate to the next,
and 2021-only conveniences (disjoint closure captures, IntoIterator
for arrays by value, expanded prelude with `TryFrom`/`TryInto`/
`FromIterator`) silently degraded as soon as code crossed the
edition boundary.

This aligns both crates on edition 2021 to match buildkit-proto. The
bump compiles clean - `cargo build --workspace --all-targets` passes,
`cargo fix --workspace --edition-idioms` finds no auto-fixable
idiom drift, and the existing 44 tests still pass.

While here, drops two `use std::convert::TryFrom;` statements in
buildkit-frontend/src/oci.rs that became redundant: the 2021 prelude
imports `TryFrom` (and `TryInto`) automatically, so the `impl
TryFrom<String> for ExposedPort` and the `u64::try_from(...)` call in
the `opt_duration_nanos` helper module no longer need an explicit
import.

`cargo clippy --workspace --all-targets -- -D warnings` stays clean.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
Aligns dev-dep pins with the rest of the workspace and brings them up
to current. None of these affect the public API or runtime - they only
gate the example and test compilation:

  - env_logger      0.6  -> 0.11   (0.6 dates from 2019)
  - pretty_assertions 0.6 -> 1.4   (post-1.0 stable)
  - regex           1.3  -> 1.11   (buildkit-llb already uses 1.11.x)
  - url             2.1  -> 2.5

`cargo update --dry-run --verbose` still reports five upstream majors
behind (`tonic`/`tonic-build` 0.12 -> 0.14, `prost`/`prost-types`
0.13 -> 0.14, `sha2` 0.10 -> 0.11) - those are intentional API
breaks comparable to the 0.1 -> 0.12 tonic migration we did earlier
and warrant separate, scoped commits, not a drive-by bump.

`cargo test --workspace` (44 tests) and `cargo clippy --workspace
--all-targets -- -D warnings` both stay clean.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
`pb::TmpfsOpt` is `#[derive(Copy)]` since prost only ever generates
`Copy` for plain-scalar messages, so the `opt.clone()` introduced in
d230692 ("feat: Implement missing commands and options") trips
clippy::clone_on_copy. Just dereference the borrow. No behavior
change.

https://claude.ai/code/session_01XtZHcL6rKJDuX7tUS3okdc
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.

2 participants