From ce21a565dd5bd5c723c39495b602d39f230a16ac Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Mon, 15 Jun 2026 09:29:39 -0400 Subject: [PATCH] feat: add TemplateBuilderCompose SDK types and client method (#26350) > [!NOTE] > This PR was authored by Coder Agents on behalf of @jeremyruppel. Part 3 of DEVEX-277 (POST /api/v2/templatebuilder/compose). Adds SDK types and client method for the compose endpoint: - `TemplateBuilderComposeRequest` with `BaseTemplateID` and `Modules` (list of `{ID, Variables}`). Registry URL is omitted from the request; it comes from server-side deployment config. - `TemplateBuilderCompose(ctx, req)` client method that POSTs the request and returns raw `application/x-tar` bytes (matching the `Download` pattern in `codersdk/files.go`). - Generated TypeScript types updated. --- codersdk/templatebuilder.go | 29 +++++++++++++++++++++++++++++ site/src/api/typesGenerated.ts | 20 ++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/codersdk/templatebuilder.go b/codersdk/templatebuilder.go index 8b41b00773..098250fd5d 100644 --- a/codersdk/templatebuilder.go +++ b/codersdk/templatebuilder.go @@ -3,6 +3,7 @@ package codersdk import ( "context" "encoding/json" + "io" "net/http" "net/url" ) @@ -95,3 +96,31 @@ func (c *Client) TemplateBuilderModules(ctx context.Context, base string) (Templ var resp TemplateBuilderModulesResponse return resp, json.NewDecoder(res.Body).Decode(&resp) } + +// TemplateBuilderComposeRequest is the request body for +// POST /api/v2/templatebuilder/compose. +type TemplateBuilderComposeRequest struct { + BaseTemplateID string `json:"base_template_id"` + Modules []TemplateBuilderComposeModule `json:"modules"` +} + +// TemplateBuilderComposeModule identifies a module and its variable +// values for the compose request. +type TemplateBuilderComposeModule struct { + ID string `json:"id"` + Variables map[string]string `json:"variables,omitempty"` +} + +// TemplateBuilderCompose renders a base template with the selected +// modules and returns the resulting tar archive bytes. +func (c *Client) TemplateBuilderCompose(ctx context.Context, req TemplateBuilderComposeRequest) ([]byte, error) { + res, err := c.Request(ctx, http.MethodPost, "/api/v2/templatebuilder/compose", req) + if err != nil { + return nil, err + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return nil, ReadBodyAsError(res) + } + return io.ReadAll(res.Body) +} diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index dce48dfb84..f63f476f7d 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -8172,6 +8172,26 @@ export interface TemplateBuilderBasesResponse { readonly bases: readonly TemplateBuilderBase[]; } +// From codersdk/templatebuilder.go +/** + * TemplateBuilderComposeModule identifies a module and its variable + * values for the compose request. + */ +export interface TemplateBuilderComposeModule { + readonly id: string; + readonly variables?: Record; +} + +// From codersdk/templatebuilder.go +/** + * TemplateBuilderComposeRequest is the request body for + * POST /api/v2/templatebuilder/compose. + */ +export interface TemplateBuilderComposeRequest { + readonly base_template_id: string; + readonly modules: readonly TemplateBuilderComposeModule[]; +} + // From codersdk/deployment.go export interface TemplateBuilderConfig { readonly disabled?: boolean;