🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

feat: add TemplateBuilderCreateTemplate SDK types and client method - #26360

Merged
jeremyruppel merged 9 commits into
mainfrom
jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template
Jun 15, 2026
Merged

feat: add TemplateBuilderCreateTemplate SDK types and client method#26360
jeremyruppel merged 9 commits into
mainfrom
jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template

Conversation

@jeremyruppel

@jeremyruppel jeremyruppel commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Adds POST /api/v2/templatebuilder/compose/template, a synchronous endpoint that composes a template from a base and modules, validates it via a provisioner import job, and creates the template in a single request.

The handler composes terraform files, bundles them as a tar, inserts the file with hash-based dedup, creates a template version with an import job, waits up to 2 minutes for the job to complete, classifies errors for known failure modes (network-unreachable registry, DNS failures), then creates the template on success. Canceled and failed jobs return appropriate error responses.

Also adds hclwrite.Format to composed terraform output for canonical HCL formatting.

Closes https://linear.app/codercom/issue/DEVEX-279

Implementation notes
  • SDK types and client method in codersdk/templatebuilder.go with validation tags matching the standard template creation path (template_display_name, lt=128)
  • ClassifyProvisionerError in coderd/templatebuilder/errors.go detects DNS, connection refused, i/o timeout, and TLS handshake failures and returns actionable messages
  • waitForProvisionerJob polls with a ramp-up interval schedule (100ms, 200ms, 500ms, then 1s steady) and accepts an onUpdate callback for future SSE streaming
  • Audit logging for both template and template version creation
  • TOCTOU name uniqueness: early check for fast feedback, DB unique constraint catch for the race window (returns 409, not 500)
  • Swagger annotations for all error responses (400, 404, 409, 504)

🤖 Generated by Coder Agents

@linear-code

linear-code Bot commented Jun 12, 2026

Copy link
Copy Markdown

DEVEX-279

@github-actions

Copy link
Copy Markdown

Docs preview

📖 View docs preview for docs/reference/api/schemas.md

@jeremyruppel jeremyruppel changed the title feat(codersdk): add TemplateBuilderCreateTemplate SDK types and client method feat: add TemplateBuilderCreateTemplate SDK types and client method Jun 15, 2026
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-278-be-input-validation-sanitization branch from 5018709 to 3cd22c6 Compare June 15, 2026 13:02
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template branch 2 times, most recently from 7385ad6 to a47b263 Compare June 15, 2026 13:21
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-278-be-input-validation-sanitization branch 2 times, most recently from 58852e9 to 9b66c67 Compare June 15, 2026 13:30
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template branch 2 times, most recently from 6237dee to 9c6139e Compare June 15, 2026 13:33
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-278-be-input-validation-sanitization branch from 9b66c67 to 374925a Compare June 15, 2026 13:33
@jeremyruppel
jeremyruppel marked this pull request as ready for review June 15, 2026 13:38
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-278-be-input-validation-sanitization branch from 374925a to f77d6bb Compare June 15, 2026 14:09
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template branch 2 times, most recently from 9c90ded to 80cc7d6 Compare June 15, 2026 15:10
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-278-be-input-validation-sanitization branch from f77d6bb to 6c99fc7 Compare June 15, 2026 15:10
@jeremyruppel
jeremyruppel requested a review from aslilac June 15, 2026 15:12
Base automatically changed from jeremy/devex-278-be-input-validation-sanitization to main June 15, 2026 15:34
Add the compose endpoint that accepts a base template ID and optional
modules with variable overrides, renders them into Terraform source
files via Compose/BundleTar, and returns the tar archive directly.

The handler reads the registry URL from the deployment config
(CODER_TEMPLATE_BUILDER_REGISTRY_URL), validates the request, and
returns the rendered tar with Content-Type: application/x-tar.

Includes swagger annotations, route wiring, and integration tests
covering happy path, error cases, and feature-disabled behavior.
The TestEndpointsDocumented test derives expected IDs from summaries.
The @id 'compose-template-builder' did not match the kebab-cased
summary 'Compose template from base and modules'.
…talog

Reusable Go script that reads the Coder registry repo and generates
module.json and .tf.tmpl files for the template builder catalog. Parses
variable declarations from main.tf, frontmatter from README.md, and
pinned versions from git tags.

Usage:
  go run ./scripts/modulegen/ -registry /path/to/registry -output coderd/templatebuilder/modules

Handles escaped quotes and heredoc descriptions, skips variables with
heredoc defaults (cannot be represented in the builder UI), uses numeric
semver sorting for version tags, and exits non-zero on failures.
…t method

Add request/response types and client method for the new
POST /api/v2/templatebuilder/compose/template endpoint that will
compose a template and create it in a single request.

The request embeds compose parameters (base_template_id, modules)
alongside template creation parameters (organization_id, name,
display_name, description, icon, provisioner_tags).
Add ClassifyProvisionerError to detect known terraform init failure
modes (DNS resolution, connection refused, i/o timeout, TLS handshake
timeout) and return actionable user-facing messages. Unknown errors
pass through unchanged.
Add a synchronous endpoint that composes a template from a base and
modules, validates it via a provisioner import job, and creates the
template in a single request.

The handler: composes terraform files, bundles them as a tar archive,
inserts the file with hash-based dedup, creates a template version
with an import job, waits for the job to complete (2-minute timeout),
classifies any errors, then creates the template on success.

The waitForProvisionerJob helper uses an exponential backoff poll loop
with an onUpdate callback hook for future SSE streaming support.

Route: POST /api/v2/templatebuilder/compose/template
Apply canonical HCL formatting to rendered MainTF and ModulesTF
output using hclwrite.Format. This produces consistently formatted
terraform files regardless of template indentation.

The formatHCL helper returns input unchanged if it is empty.
@jeremyruppel
jeremyruppel force-pushed the jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template branch from 80cc7d6 to c49798e Compare June 15, 2026 15:35
@jeremyruppel
jeremyruppel merged commit de31c7c into main Jun 15, 2026
35 checks passed
@jeremyruppel
jeremyruppel deleted the jeremy/devex-279-be-post-apiv2templatebuildercompose-validation-template branch June 15, 2026 22:12
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants