Add reproducible protoc toolchain and proto-check CI (#307) - #445
Add reproducible protoc toolchain and proto-check CI (#307)#445carlosvales wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a pinned, Docker-based protoc + protoc-gen-go toolchain and a CI workflow to ensure committed *.pb.go outputs stay in sync with the pinned generator versions, preventing version-drift diffs.
Changes:
- Add
Dockerfile.protocto build a reproducible protoc toolchain image (pinned protoc + protoc-gen-go via build args). - Extend
Makefilewithproto-builder,proto-gen-docker, andproto-checktargets to regenerate and verify protobuf outputs via Docker. - Add
.github/workflows/protos.ymlto runmake proto-checkon relevant changes; regenerate*.pb.gofiles to match the pinned generator output.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Dockerfile.protoc | Introduces Dockerized protoc/protoc-gen-go toolchain used for deterministic generation. |
| Makefile | Adds Docker-based proto generation + a proto-check gate intended for CI. |
| .github/workflows/protos.yml | Runs make proto-check on PRs/pushes when proto/tooling files change. |
| pkg/protocol/protobuf/vcsec/vcsec.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
| pkg/protocol/protobuf/universalmessage/universal_message.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
| pkg/protocol/protobuf/signatures/signatures.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
| pkg/protocol/protobuf/carserver/vehicle.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
| pkg/protocol/protobuf/carserver/common.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
| pkg/protocol/protobuf/carserver/car_server.pb.go | Regenerated output (cosmetic comment lines) to match pinned toolchain. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| && curl -fsSL -o /tmp/protoc.zip \ | ||
| "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" \ | ||
| && unzip -q /tmp/protoc.zip -d /usr/local/protoc \ | ||
| && rm /tmp/protoc.zip \ | ||
| && chmod +x /usr/local/protoc/bin/protoc |
There was a problem hiding this comment.
The Dockerfile downloads the protoc zip from GitHub but doesn't verify its checksum/signature. Since this image is intended to gate CI and provide reproducible output, it would be safer and more deterministic to validate the downloaded archive (e.g., check SHA256 from the release assets) before unzipping/using it.
| docker run --rm \ | ||
| -v "$(CURDIR):/workspace" \ | ||
| -w /workspace \ | ||
| $(PROTOC_IMAGE) \ | ||
| --proto_path $(PROTO_DIR) \ | ||
| --go_out $(PROTO_DIR) \ | ||
| --go_opt=module=github.com/teslamotors/vehicle-command/pkg/protocol/protobuf \ | ||
| $(PROTO_FILES) |
There was a problem hiding this comment.
proto-gen-docker runs the container as root and writes generated *.pb.go files back into the working tree. On many hosts this will leave root-owned files in pkg/protocol/protobuf/**, which is painful to clean up and can break subsequent local tooling. Consider running the container with the current UID/GID (e.g., docker run --user ...) so generated files keep normal ownership.
| # regenerated code; run `make proto-gen-docker` and commit the result | ||
| # in the same change. | ||
|
|
||
| FROM golang:1.23-bookworm AS toolchain |
There was a problem hiding this comment.
For a reproducible toolchain image, FROM golang:1.23-bookworm is a floating tag and can change over time (new patch versions / rebuilds), which can introduce drift unrelated to protoc/protoc-gen-go. Pinning to a specific patch tag (e.g., golang:1.23.0-bookworm) or an image digest would better match the goal of this PR.
| FROM golang:1.23-bookworm AS toolchain | |
| FROM golang:1.23.0-bookworm AS toolchain |
|
Thanks for putting up this PR and apologies that it hasn't gotten review sooner. It looks good, with one minor issue: Please remove the Windows-style line endings ( |
|
Thanks @sethterashima! Done — I've removed the Windows-style CRLF line endings from the Makefile (it's LF now). The new commit only touches line endings, no content or target changes. Let me know if there's anything else before merge. |
Regenerate existing protobuf files using a consistent compiler version in preperation for merging #445.
Closes teslamotors#307. Currently, regenerating the .pb.go files relies on whatever protoc the contributor happens to have installed locally, which leads to spurious diffs when versions drift. This change introduces a pinned, reproducible toolchain and a CI gate that fails when the committed *.pb.go files do not match what the pinned toolchain produces. Changes: - Add Dockerfile.protoc, a Debian-based image that installs protoc 3.21.9 and protoc-gen-go v1.28.1 (the versions stamped in the headers of the existing *.pb.go files). Both are configurable via build args so future bumps require only one place to edit. - Add three Makefile targets: * proto-builder builds the toolchain image * proto-gen-docker regenerates the .pb.go files using the toolchain * proto-check regenerates and fails if git sees any diff The original `proto-gen` target (host protoc) is kept untouched for backwards compatibility. - Add .github/workflows/protos.yml. Runs `make proto-check` on PRs and pushes that touch the .proto files, the toolchain Dockerfile, the Makefile, or the workflow itself. - Regenerate *.pb.go using the pinned toolchain. The diff is purely cosmetic: protoc-gen-go v1.28.1 emits an empty `//` comment line in "Types that are assignable to ..." blocks that the previously committed files lacked, which suggests they were generated with a slightly different protoc-gen-go than their headers claim. Bringing the committed output in line with the pinned toolchain is necessary for proto-check to pass on a clean tree.
…ost UID Three follow-ups suggested by the automated review: - Dockerfile.protoc: pin the base image to `golang:1.23.0-bookworm` instead of the floating `golang:1.23-bookworm` tag, so a future patch rebuild of that tag cannot quietly change the toolchain output. - Dockerfile.protoc: verify the SHA256 of the downloaded protoc archive before unzipping. The expected sums for both linux-x86_64 and linux-aarch_64 (computed against the official v21.9 release assets) are exposed as build args so they live next to PROTOC_VERSION and are easy to update together. - Makefile: pass `--user "$(id -u):$(id -g)"` to `docker run` so generated *.pb.go files are owned by the invoking user instead of root, avoiding permission breakage on Linux/macOS hosts after running proto-gen-docker. Verified locally: the rebuilt image still produces a clean tree (`make proto-check` exits 0 with no diff under pkg/protocol/protobuf/).
Remove Windows-style CRLF line endings from the Makefile as requested in review. Only line endings change; no content or target modifications.
8cb40c7 to
7632f58
Compare
|
Rebased on Now that 4c2143a ( Ready for another CI run whenever you can approve the workflow. Thanks! |
Description
Closes #307.
Currently, regenerating the
.pb.gofiles relies on whateverprotocthe contributor happens to have installed locally. This leads to spurious diffs whenever versions drift. This PR introduces a pinned, reproducible toolchain and a CI gate that fails when the committed*.pb.gofiles do not match what the pinned toolchain produces.Changes
Dockerfile.protocA Debian-based image (
golang:1.23-bookworm) that installs:protoc3.21.9 (upstream tagv21.9)protoc-gen-gov1.28.1These match the versions stamped in the headers of the existing
*.pb.gofiles. Both are configurable via build args so future bumps only need to edit two lines (Dockerfile + Makefile).Makefiletargetsproto-buildervehicle-command-protoc:21.9-1.28.1).proto-gen-docker.pb.gofiles using the pinned toolchain.proto-checkgit diffis non-empty underpkg/protocol/protobuf/.The original
proto-gentarget (hostprotoc) is kept untouched for backwards compatibility — contributors who want to keep using their local toolchain can still do so..github/workflows/protos.ymlRuns
make proto-checkon PRs and pushes tomainthat touch the.protofiles, the toolchain Dockerfile, the Makefile, or the workflow itself.Regenerated
*.pb.goSix files are touched (
+257 / -0). The diff is purely cosmetic:protoc-gen-gov1.28.1 emits an empty//comment line at the top of each "Types that are assignable to ..." block that the previously committed files lacked. This suggests the committed files were generated with a slightly differentprotoc-gen-gothan their headers claim. Bringing the committed output in line with the pinned toolchain is necessary forproto-checkto pass on a clean tree.A representative hunk:
// Types that are assignable to ActionMsg: +// // *Action_VehicleAction ActionMsg isAction_ActionMsg \`protobuf_oneof:\"action_msg\"\`No type signatures, field tags, or runtime behavior change.
Type of change
Checklist:
(Documentation/unit tests not applicable: tooling-only PR, the new CI workflow is the test.)