Skip to content

refactor(protoc): migrate to protocompile experimental compiler for Edition 2024#404

Open
Kybxd wants to merge 4 commits into
masterfrom
edition-2024
Open

refactor(protoc): migrate to protocompile experimental compiler for Edition 2024#404
Kybxd wants to merge 4 commits into
masterfrom
edition-2024

Conversation

@Kybxd

@Kybxd Kybxd commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Why

Protobuf Edition 2024 is not understood by bufbuild/protocompile's stable Compiler. To unblock Edition 2024 schemas, we follow the same path Buf itself took in buf v1.69.0 and switch the internal protoc wrapper to protocompile's experimental compiler, which has Edition 2024 support.

What changes vs. the stable compiler

The experimental compiler exclusively consumes source files via source.Opener. It no longer accepts pre-compiled FileDescriptors through protoregistry.GlobalFiles — which is how the stable compiler used to pick up tableau/protobuf/*.proto and buf/validate/validate.proto. We need a new mechanism to make those imports resolvable at compile time.

How

Expose the required .proto sources through go:embed and feed them to protocompile via a custom fs.FS:

Import path Source of truth Vendored?
tableau/protobuf/tableau.proto proto/tableau/protobuf/tableau.proto (embedded via tableauprotobuf.FS) no
tableau/protobuf/wellknown.proto proto/tableau/protobuf/wellknown.proto (embedded via tableauprotobuf.FS) no
buf/validate/validate.proto buf export of buf.build/bufbuild/protovalidate pinned in buf.lock yes, under internal/x/xproto/protoc/embedded/

Standard imports (google/protobuf/*) continue to be served by source.WKTs and need no embedding.

Single source of truth for tableau protos

A new proto/tableau/protobuf/embed.go exposes tableauprotobuf.FS (//go:embed tableau.proto wellknown.proto, matching buf.yaml's top-level-only scope), and internal/x/xproto/protoc/embed.go composes it with the vendored buf/validate/ tree behind a small layeredFS that routes tableau/protobuf/* reads to tableauprotobuf.FS and everything else to the embedded buf-validate export. This means the compiler always sees the exact same tableau proto text that ships in proto/tableau/protobuf/, with no risk of a stale second copy.

Refresh workflow for protovalidate

A go:generate directive in embed.go invokes gen_embedded.sh, which:

  1. Wipes embedded/ and recreates embedded/buf/validate/.
  2. Reads the protovalidate commit out of buf.lock and forwards it to buf export buf.build/bufbuild/protovalidate:<commit>.

⚠️ buf export <remote-module> does not consult the workspace's buf.lock — that file only governs intra-workspace transitive resolution. Without an explicit commit suffix, buf export would pull the latest published commit. The script reads the commit from buf.lock so the vendored copy stays in sync automatically.

Why is embedded/ checked into version control?

So that downstream consumers of go install github.com/tableauio/tableau/cmd/tableauc@latest can build without buf installed and without running go generateproxy.golang.org only packages git-tracked files.

Upgrading protovalidate

buf dep update          # bumps buf.lock
go generate ./...       # refreshes embedded/buf/validate/
git add -A && git commit

Diff summary

7 files changed, mostly the vendored buf/validate/validate.proto (~5.1k lines):

  • internal/x/xproto/protoc/compiler.go — switch to experimental compiler, wire source.Opener against the layered fs.FS.
  • internal/x/xproto/protoc/embed.gogo:embed for buf/validate/, layeredFS, and refresh-workflow docs.
  • internal/x/xproto/protoc/gen_embedded.sh — refresh script driven by buf.lock.
  • internal/x/xproto/protoc/embedded/buf/validate/validate.proto — vendored protovalidate schema.
  • proto/tableau/protobuf/embed.go — new tableauprotobuf.FS exposing this repo's own proto sources.
  • go.mod / go.sum — protocompile experimental dep.

@codecov

codecov Bot commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.81081% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.42%. Comparing base (1c5fee6) to head (017b7ce).

Files with missing lines Patch % Lines
internal/x/xproto/protoc/compiler.go 58.46% 18 Missing and 9 partials ⚠️
internal/x/xproto/protoc/embed.go 77.77% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #404      +/-   ##
==========================================
- Coverage   75.60%   75.42%   -0.19%     
==========================================
  Files          88       89       +1     
  Lines        9527     9565      +38     
==========================================
+ Hits         7203     7214      +11     
- Misses       1749     1767      +18     
- Partials      575      584       +9     

☔ 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.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJul 13, 2026, 12:06 PM

@Kybxd Kybxd changed the title refactor(protoc): migrate to protocompile experimental compiler with embedded proto deps refactor(protoc): migrate to protocompile experimental compiler for Edition 2024 Jul 10, 2026
Kybxd added 4 commits July 13, 2026 20:06
The experimental compiler only accepts source files via source.Opener, so
vendor required .proto deps under internal/x/xproto/protoc/embedded/ and
expose them through go:embed:

  - tableau/protobuf/*.proto: copied from proto/tableau/protobuf/
  - buf/validate/validate.proto: exported from buf.build/bufbuild/protovalidate
    at the commit pinned in buf.lock

gen_embedded.sh (invoked via go:generate) refreshes the embedded tree and
explicitly forwards buf.lock's protovalidate commit to `buf export`, since
ad-hoc `buf export` does not consult buf.lock. The embedded/ tree is
committed so `go install ...@latest` works without buf or go generate.
Regenerate embedded/tableau/protobuf/tableau.proto, wellknown.proto and
embedded/buf/validate/validate.proto to sync with the aggregate field
added to FieldProp in proto/tableau/protobuf/tableau.proto (PR #395).
The stale embedded copy caused test/functest failures:
"cannot resolve message field name for tableau.FieldProp".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant