> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Part 2 of DEVEX-277 (POST /api/v2/templatebuilder/compose).
Adds the core composition and bundling logic for the template builder.
`Compose` renders a base template and selected modules into Terraform source files. It validates modules before rendering (rejects duplicates, ConflictsWith violations, unknown IDs, OS incompatibility), then for each module merges manifest defaults with caller-supplied variable overrides and renders the module template.
`mergeModuleVariables` fills in defaults for non-computed, non-sensitive variables from the manifest (with basic JSON type validation via `isSimpleJSONValue`), uses `null` for non-required variables without defaults, and leaves required variables absent so `missingkey=error` catches omissions at render time.
`BundleTar` packages the result into a tar archive with reproducible timestamps. Writes `main.tf` always, `modules.tf` only when modules are present.
Conflict detection is bidirectional so module ordering in the request does not affect validation.
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Part 1 of DEVEX-277 (POST /api/v2/templatebuilder/compose).
Adds module rendering support and agent resource name extraction to the template builder, preparing for the compose endpoint.
- `ModuleRenderContext` and `RenderModuleTemplate` for rendering module `.tf.tmpl` files with registry URL, pinned version, agent resource name, and variable values. Nil-guards the Variables map to prevent panics.
- Extract shared `renderTemplate` with `missingkey=error` so missing variable keys fail loudly instead of producing `<no value>` in rendered HCL.
- `ExtractAgentResourceName` uses a regex to find the `coder_agent` resource name from rendered base HCL. Errors unless exactly one agent is found.
- `ModuleTemplateFS` exposes module template files from the embedded catalog, with validation that the expected `.tf.tmpl` file exists (`fs.Sub` on `embed.FS` silently succeeds for nonexistent paths).
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Runs the `scripts/modulegen` generator against the coder/registry to produce the initial module catalog for the template builder. Generates `module.json` and `.tf.tmpl` files for 19 modules across four categories:
- **IDE**: code-server, jetbrains, vscode-desktop, vscode-web, cursor, windsurf, zed, kiro
- **AI Agent**: claude-code, aider, goose, amazon-q
- **Source Control**: git-clone, git-config, git-commit-signing
- **Utility**: dotfiles, personalize, filebrowser, jupyterlab
Also updates `catalog_test.go` to validate the new embedded modules load correctly.
Implement `GET /api/v2/templatebuilder/modules`, which returns the
filtered list of modules available for a given base template. Reads from
the bundled catalog via `LoadModules()` and applies OS-compatibility
filtering based on the `base` query param.
Computed variables (e.g. `agent_id`) are excluded from the API response
at the `ToSDK()` conversion boundary since they are wired automatically
by the builder. The `Computed` field is removed from the SDK type. Adds
`CompatibleWithOS()` to `ModuleManifest` for OS filtering.
Returns 400 for unknown base IDs and 404 when the template builder is
disabled.
Depends on #26116
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Add the bundled `exampleID -> OS` Go map for Docker, Kubernetes, and AWS
EC2 Linux base templates. Create `.tf.tmpl` Go template files for each
within `coderd/templatebuilder/bases/`, along with `BaseRenderContext`
and `RenderBaseTemplate` rendering helpers.
The `.tf.tmpl` files are independent copies of the example templates
with module blocks (code-server, jetbrains) removed, since the template
builder composes modules separately into `modules.tf`. When
`ImageOptions` is provided, the container image field references the
Terraform parameter; otherwise it uses the hardcoded value via Go
template whitespace control (`{{-`).
Golden file snapshot tests verify rendered output stability with an
`-update` flag for regeneration.
Depends on #25909
> [!NOTE]
> This PR was authored by Coder Agents on behalf of @jeremyruppel.
Scaffolds the `coderd/templatebuilder` package for the guided template
builder ([DEVEX-272](https://linear.app/codercom/issue/DEVEX-272),
[RFC](https://www.notion.so/coderhq/RFC-Guided-Template-Creation-Workflow-342d579be59280dfbf8eea2e5006dbda)).
Adds the module catalog types and `go:embed` wiring that the template
builder endpoints will use:
- `codersdk.TemplateBuilderModule`, `TemplateBuilderModuleVariable`, and
related types matching the RFC schema
- Internal `ModuleManifest` type with `go:embed` wiring to bundle
`module.json` files from `coderd/templatebuilder/modules/`
- `LoadModules()` with defensive copy, unexported
`parseModulesFromFS(fs.FS)` for test isolation, `ToSDK()` conversion
- Real `code-server` module manifest as the first catalog entry
- Strict validation: ID uniqueness, version non-empty, variable
type/name validation, `DisallowUnknownFields`, and requiring
`module.json` in every module directory
- Tests via internal `catalog_internal_test.go` (for
`parseModulesFromFS` with `fstest.MapFS` fixtures) and external
`catalog_test.go` (for `LoadModules` and `ToSDK`), covering multi-module
parsing, all variable types, validation errors, nil-slice normalization,
and full SDK field assertions
> [!NOTE]
> Generated with [Coder Agents](https://coder.com/agents) by
@jeremyruppel
---------
Co-authored-by: McKayla はな <mckayla@hey.com>