Extend Gitlab::Kas::Client to support events_platform Publish and Subscribe
## Summary Extend the existing `Gitlab::Kas::Client` class ([`lib/gitlab/kas/client.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/kas/client.rb)) to support the `events_platform` gRPC service. This adds `Publish` and `Subscribe` capabilities so Rails can produce and consume CloudEvents through GitLab Relay (KAS). ## Why this approach (and not a separate gem) The original plan was to build a new Ruby gem. After review extending `Gitlab::Kas::Client` is a better fit: - **Pattern is established.** The class already wraps gRPC stubs for AutoFlow, Notifications, ConfigurationProject, ManagedResources, etc. Adding events_platform follows the same pattern. - **Auth, TLS, JWT, and timeouts are already handled.** Reused as-is. - **Lower risk and faster delivery** than packaging a new gem. - **Doesn't preclude extraction.** If a non-Rails Ruby caller emerges, the code can move to `vendor/gems/` or a separate repo. ## Scope ### 1. Register the events_platform stub Add an entry to `STUB_CLASSES` in `Gitlab::Kas::Client`: ```ruby events_platform: Gitlab::Agent::EventsPlatform::Rpc::EventsPlatform::Stub ``` (Verify the Ruby protobuf stubs are exported from gitlab-agent. AutoFlow's stubs are vendored — same export mechanism should cover events_platform.) ### 2. `publish_event` method Single method that wraps the unary `Publish` RPC. Follows the existing pattern (see `send_autoflow_event` for reference). ```ruby def publish_event(topic:, event:) request = Gitlab::Agent::EventsPlatform::Rpc::PublishRequest.new( topic: topic, events: [event] ) stub_for(:events_platform) .publish(request, metadata: metadata) .message_ids end ``` ### 3. `subscribe_events` method (bidi streaming) Block-based API that hides the bidi protocol details: ```ruby client.subscribe_events( topic: 'gitlab.external', consumer_group: 'gitlab-rails' ) do |event| # If this block raises, no ack — message will be redelivered. # If it returns successfully, ack is sent automatically. Gitlab::EventStore.publish(translate(event)) end ``` Implementation handles: - Sending `SubscribeConfig` as the first message - Receiving `SubscribeResponse` events - Sending `Ack` messages back on the same stream after successful block return - Reconnecting on stream break (or failing fast — TBD during implementation) ### 4. Tests - Unit tests for `publish_event` (mock the stub) - Unit tests for `subscribe_events` block lifecycle (mock the bidi stream) - Integration test if feasible (against a local KAS in CI) ## Out of scope - The external producer endpoint and PAT/OAuth auth (out of scope until the external API is designed). ## References - [Subscribe Contract design doc (!19605)](https://gitlab.com/gitlab-com/content-sites/handbook/-/merge_requests/19605) — defines the gRPC contract this implements - [Existing `Gitlab::Kas::Client`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/kas/client.rb) — pattern to follow - Parent epic: https://gitlab.com/groups/gitlab-org/-/work_items/21346
issue