Pin code generation, split it into its own workflow, add renovate.json - #124
Open
biglittlebigben wants to merge 2 commits into
Open
Pin code generation, split it into its own workflow, add renovate.json#124biglittlebigben wants to merge 2 commits into
biglittlebigben wants to merge 2 commits into
Conversation
biglittlebigben
force-pushed
the
renovate/pin-generators-and-baseline
branch
from
August 25, 2026 16:11
58fdc72 to
509d4dd
Compare
The generate path here pinned almost nothing. CI installed protoc-gen-go
at v1.28.1 while go.mod carried protobuf v1.36.11, asked
arduino/setup-protoc for `3.x`, ran mage from `mage-action` with
`version: latest`, and set up Go with `>=1.22` against a go.mod
requiring 1.25.5. The magefile also passed `--plugin=go=`, the short
form protoc silently ignores, so generation ran whatever protoc-gen-go
happened to be on PATH rather than the resolved one.
The committed output showed the drift: every generated file was written
by protoc-gen-go v1.36.4 - matching neither go.mod nor CI - and
internal.pb.go by protoc v5.28.2 where the rest used v4.23.4.
Pin what writes the code:
- protoc-gen-go and mage become `tool` directives in go.mod, resolved
at generation time with `go tool -n`
- the `--plugin=` flag uses the full-executable-name form protoc
honours
- protoc is pinned to the release that generated most of the tree,
rather than a `3.x` range
- CI reads go-version-file: go.mod, so one pin covers build and test
protoc-gen-psrpc is deliberately NOT pinned: it is this repo's own
command, built from the tree by `go install ./protoc-gen-psrpc` so the
fixtures exercise the plugin as it currently is. Because the fixtures
invoke protoc directly through go:generate, Generate() now puts the
pinned protoc-gen-go on PATH for them - without it, dropping the CI
install step would leave no protoc-gen-go at all.
Generation of the committed output moves into generate.yaml: it runs on
branch pushes, regenerates with the pinned toolchain and commits the
result. test.yaml keeps its own generation because it has to -
internal/test gitignores **/*.psrpc.go, so the fixtures the tests
compile against do not exist in a fresh checkout and `mage testall` must
build them before anything compiles.
generate.yaml replaces an add-and-commit step that arrived, copied in
from elsewhere, with the commit that first added protoc-gen-psrpc -
complete with an `add: livekit` path. That directory has never existed
here, so the step silently committed nothing for its whole life.
This could not land as a no-op. protoc-gen-go and the protobuf runtime
are one module, so pinning the plugin to the v1.36.4 that wrote these
files would mean downgrading the library too. Pinning to go.mod's
v1.36.11 and regenerating is the smaller change, so this commit carries
that regeneration. It is representational only: across all 21 committed
generated files the sole difference is protobuf-go emitting the
descriptor as `const x = "" + "..."` instead of
`var x = string([]byte{0x0a, ...})`, plus version headers. No struct,
getter or field changed. The full suite passes against the regenerated
tree, including from a state with the gitignored fixtures deleted.
renovate.json is new: the org baseline for a library, with third-party
modules ungrouped so a bad bump reverts alone, livekit deps grouped and
exempt from quarantine, a vulnerability fast path, and both the go and
toolchain directives disabled, since this module's go directive is the
minimum we ask of consumers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeQL flagged generate.yaml for relying on the default GITHUB_TOKEN permissions. Its suggested starting point of `contents: read` would not work here - add-and-commit pushes the regenerated output, so the job needs `contents: write`. test.yaml gets `contents: read`, which is all it uses: setup-protoc's repo-token only reads release metadata. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
biglittlebigben
force-pushed
the
renovate/pin-generators-and-baseline
branch
from
August 25, 2026 17:03
49e948c to
62b440d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third of three, after livekit/protocol#1733 and livekit/cloud-protocol#1305. This repo needed the most work and is the only one that could not land as a no-op — details below.
Why
The generate path pinned almost nothing, and four separate versions of the same thing disagreed:
setup-protocwas asked for3.xsetup-gowas also ongo-version: '>=1.22'against a go.mod requiring 1.25.5, and mage came frommage-actionwithversion: latest.On top of that the magefile passed the short
--plugin=form:protoc only honours the full-executable-name form, so generation ran whatever protoc-gen-go was on PATH rather than the resolved one. The drift shows up in the tree itself:
internal.pb.gowas written by protoc v5.28.2 while everything else used v4.23.4.Pinning
tooldirectives in go.mod, resolved withgo tool -n.--plugin=flag uses the form protoc honours.3.xrange.go-version-file: go.mod, so one pin covers build and test.protoc-gen-psrpcis deliberately not pinned. It's this repo's own command, built from the tree bygo install ./protoc-gen-psrpc— the fixtures exist to exercise the plugin as it currently is, so pinning it to a release would defeat the point.That has a consequence worth flagging: the fixtures under
internal/test/invoke protoc directly viago:generate, so they take plugins off PATH.Generate()now puts the pinned protoc-gen-go on PATH for them. Without that, dropping the CIgo install protoc-gen-go@v1.28.1step would have left no protoc-gen-go available at all.Workflow split
Generation of the committed output moves into a new
generate.yaml, modelled on protocol's: runs on branch pushes, regenerates with the pinned toolchain, commits the result.test.yamlkeeps its own generation, because it has to.internal/test/.gitignorecontains**/*.psrpc.go, so the psrpc half of every fixture is a build artifact that does not exist in a fresh checkout — the tests reference symbols from it (NewMyServiceServerand friends), somage testallhas to generate before anything compiles. What did change there: the four@latestinstalls andmage-actionare gone, protoc is pinned, and Go comes fromgo.mod.generate.yamlreplaces anadd-and-commitstep that was dead for its entire life. It was copied from protocol in4e4425e, the commit that first added protoc-gen-psrpc, together with protocol'sadd: livekit.livekit/is correct in protocol — it holds that repo's generated Go code — but searching every commit here for an addition underlivekit/returns zero. The directory has never existed in psrpc; committed generated code lives ininternal/,testutils/andprotoc-gen-psrpc/options/.add-and-commitwarns and commits nothing when its path matches nothing, and doesn't fail the job, which is why it went unnoticed for ~3 years.Why this one isn't a no-op
The other two PRs verified with "regenerate → empty diff". That's impossible here: protoc-gen-go and the protobuf runtime are the same module, so pinning the plugin to the v1.36.4 that wrote these files would mean downgrading the runtime library to v1.36.4 as well. Pinning to go.mod's existing v1.36.11 and regenerating is the smaller, safer change, so this PR carries that regeneration.
It is representational only. Across all 21 committed generated files the entire non-header diff is protobuf-go changing how it emits the descriptor:
Verified mechanically — filtering the diff down to lines that are neither descriptor payload nor version headers leaves exactly that one construct in each file and nothing else. No struct, getter, or field changed.
go build ./...passes, and the full suite passes against the regenerated tree — including from a state with the gitignored*.psrpc.gofixtures deleted, which is what a CI checkout actually looks like.renovate.json
New file — this repo had none. The org baseline for a library: third-party modules ungrouped so a bad bump reverts alone,
livekit depsgrouped and exempt from quarantine, a vulnerability fast path, and both thegoandtoolchaindeptypes disabled, since this module'sgodirective is the minimum we ask of consumers.No pion group (no pion dependencies) and no
GOPRIVATE(all dependencies public). Sincehelpers:pinGitHubActionDigestsis included, Renovate will pin the remaining floating action tags inslack-notifier.yamlon its first run.🤖 Generated with Claude Code