Skip to content

refactor(proto): adopt the connect-go simple API - #352

Merged
GeertJohan merged 2 commits into
masterfrom
connect-simple
Aug 8, 2026
Merged

refactor(proto): adopt the connect-go simple API#352
GeertJohan merged 2 commits into
masterfrom
connect-simple

Conversation

@GeertJohan

Copy link
Copy Markdown
Member

Summary

Migrates all Go connect code to the protoc-gen-connect-go simple option (connectrpc/connect-go#851, shipped in v1.19). Handlers and clients now use plain message signatures — Method(ctx, *Req) (*Resp, error) — instead of connect.Request[T]/connect.Response[T] wrappers. This matches the API that connect-go v2 (connectrpc/connect-go#951) will make the default, so the eventual v2 bump becomes mostly an import change.

Two commits:

  1. deps: connect-go v1.19.1 → v1.20.0 (go.mod + protoc-gen-connect-go pin in mise.toml) plus routine genproto bumps.
  2. migration: opt: paths=source_relative,simple in all five Go proto modules (authn-api, organization-api, dcim-api, plugin-proxy, plugin-sdk metadata), 24 regenerated files, and ~230 migrated hand-written files.

Notable changes beyond the mechanical unwrapping

  • Per-call metadata moves to context. Handlers read headers via connect.CallInfoForHandlerContext(ctx) (authn-api JWT/Authorization handling); clients set per-request headers via connect.NewClientContext(ctx) (functl ensureToken, terraform refreshToken, plugin-publish withAuth — the latter redesigned from a request mutator into a context producer).
  • Interceptors are untouched — they operate on connect.AnyRequest, which simple doesn't change.
  • Terraform createIdempotent generics now take plain call funcs; a fresh client context per retry attempt carries Idempotency-Key and reads Idempotency-Status from response headers.
  • Two test suites moved from direct handler invocation to httptest servers (mint_plugin_token_test.go, terraform idempotent_create_test.go): connect exports no way to fabricate a handler-side call-info context, so header-carrying direct calls are no longer possible. Coverage is equivalent (the real wire path is now exercised).
  • Three test fakes intentionally keep the raw wrapped API (connect.Client.CallUnary) — that's the correct low-level plumbing, mirroring generated simple clients.
  • Server-streaming (organization-api metrics) keeps its *connect.ServerStream[T] parameter; only the request wrapper is dropped. Frontend codegen (connect-es) is unaffected.

Test plan

Copilot AI review requested due to automatic review settings July 29, 2026 08:15

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

PR Environment - Torn Down

The environment for this PR has been removed.

jos-
jos- previously approved these changes Aug 4, 2026

@jos- jos- 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.

LGTM. See two small comments below.

// scriptedCall serves the scripted steps from an in-process Connect server and
// returns a plain client call with the same signature as generated clients, so
// the idempotency headers travel through the real call-info plumbing.
func scriptedCall(t *testing.T, steps []scriptStep, gotKeys *[]string) func(context.Context, *authnv1.ExchangeTokenRequest) (*authnv1.ExchangeTokenResponse, error) {

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.

Small comment from Claude:

idempotent_create_test.go replaced the local fakeReq/fakeResp with an unrelated auth proto because the test now needs real messages on the wire. It works, but an idempotency test keyed on a token-exchange message reads confusingly. Either add a one-line comment saying the type is arbitrary, or define a minimal test proto.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a note to the scriptedCall doc comment that the ExchangeToken types are arbitrary and only the headers matter (59b5ae7).

return c
}

// ensureToken ensures we have a valid JWT, exchanging the API key if necessary.

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.

Suggestion from Claude: Add a guard comment to ensureToken

client.go:64-77 is safe only because the nested client
context never reaches next(). That invariant is invisible at the call site, and ensureToken
has two callers (the interceptor and the exported ExchangeToken). One line noting that creating
a client context inside an interceptor is prohibited by connect would stop a future edit from
breaking it in a way no unit test would catch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a guard comment on the NewClientContext in ensureToken: the nested client context is only for the ExchangeToken call and must never flow into next(), since connect fails requests whose call info changes mid-flight (59b5ae7).

Also bumps the protoc-gen-connect-go pin in mise.toml to match, and
picks up routine genproto updates via go mod tidy.
Generate all five Go proto modules with the protoc-gen-connect-go
"simple" option. Handlers and clients now use plain message
signatures instead of connect.Request/connect.Response wrappers,
matching the API that connect-go v2 will make the default.

Per-call metadata moves to context: handlers read headers via
connect.CallInfoForHandlerContext, clients set them via
connect.NewClientContext. Interceptors are unchanged. Two test
suites that invoked handlers directly with header-carrying requests
now go through httptest servers, since connect exports no way to
fabricate a handler-side call-info context.
@GeertJohan
GeertJohan merged commit f4ce886 into master Aug 8, 2026
38 checks passed
@GeertJohan
GeertJohan deleted the connect-simple branch August 8, 2026 19:23
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