Skip to content

feat(infrastructure): development-capable simple-webapp template#414

Merged
mjudeikis merged 2 commits into
mainfrom
feat/simple-webapp-dev-template
Jul 10, 2026
Merged

feat(infrastructure): development-capable simple-webapp template#414
mjudeikis merged 2 commits into
mainfrom
feat/simple-webapp-dev-template

Conversation

@mjudeikis

Copy link
Copy Markdown
Contributor

Why

The template catalog had exactly one development-capable template (application: frontend + backend + Postgres). An App Studio project that only needs a single-container web app — a static site, an SPA, a meme page — either got forced onto the full 3-tier stack or dead-ended in the assistant's template interview. simple-webapp itself was vestigial: no public URL, no development support, predating the Gateway API exposure work and the template-native sandbox design (docs/app-studio-template-sandboxes.md).

What

simple-webapp reworked (v0.2.0) into the single-tier counterpart of application:

  • Public exposure: HTTPRoute on the platform Gateway parent, controller-stamped expose.fqdn, status.url/host — the wiring App Studio's preview reads.
  • spec.development: one component app claiming the workspace root (workspacePath: "."), node dev image, the proven vite shim start command carried verbatim from the application frontend tier.
  • spec.dataPlane: sync/restart/env/log verbs for that component.
  • image required in production only (same CEL pattern as application); a dev-only project provisions with just {name, kedgeMode}. serviceType dropped.
  • agent.usage guidance, sampleValues, portal view.

Instance controller generalized into a table of exposed instance kinds: Application keeps the full treatment (fqdn + credentialsSecretName + OIDC bridge + finalizer); SimpleWebApp gets an exposure-only reconciler that stamps just spec.expose.fqdn — no cross-cluster state, no finalizer. A future exposed template is one line in instanceKinds.

Catalog guidance: application's agent usage now cross-points at simple-webapp for frontend-only apps (so the assistant never again reasons "only development-capable option"); redis-cache gets the agent: block it was missing.

Test: TestSeedTemplatesSimpleWebappIsDevelopmentCapable pins the contract App Studio depends on — dev component, workspace-root claim, synthesized overlay resources in the RGD, and the status fields the preview (status.url) and data plane (controlSecretRef, components) resolve through.

No app-studio changes needed — it reads development.components live from the catalog, so simple-webapp appears in the portal picker and the assistant's selectable set automatically.

Rollout note

Live environments need the provider re-seeded so the 0.2.0 Template (and its re-authored instance CRD) replaces 0.1.0 — worth confirming the seeding path updates existing Template CRs rather than create-if-absent.

Verification

go build ./..., go vet ./..., and the full go test ./... of the infrastructure provider pass. The generic TestSeedTemplatesBuildRGD runs the new template through the real RGD build including dev-overlay synthesis.

🤖 Generated with Claude Code

The template catalog had exactly one development-capable template
(application: frontend + backend + Postgres), so App Studio projects
that only need a single-container web app — a static site, an SPA —
were forced onto the full 3-tier stack or dead-ended in the assistant's
template interview. simple-webapp itself was vestigial: no public URL,
no development block, predating the Gateway API exposure work and the
template-native sandbox design.

Rework simple-webapp (v0.2.0) into the single-tier counterpart of the
application template:

- Public exposure: HTTPRoute on the platform Gateway parent, controller
  stamped expose.fqdn, status.url/host — the wiring App Studio's
  preview reads.
- spec.development: one component "app" claiming the workspace root
  (workspacePath "."), node dev image, the proven vite shim start
  command carried verbatim from the application frontend tier.
- spec.dataPlane: sync/restart/env/log verbs for that component.
- image required in production only (same CEL pattern as application);
  a dev-only project provisions with just {name, kedgeMode}.
- agent.usage guidance + sampleValues + portal view; drop serviceType.

Generalize the Application instance controller into a table of exposed
instance kinds: Application keeps the full treatment (fqdn +
credentialsSecretName + OIDC bridge + finalizer); SimpleWebApp gets an
exposure-only reconciler that stamps just spec.expose.fqdn — no
cross-cluster state, no finalizer. A future exposed template is one
line in instanceKinds.

Also: cross-point application's agent guidance at simple-webapp for
frontend-only apps, add the missing agent guidance block to
redis-cache, and pin the simple-webapp development contract in a seed
template test (dev component, workspace-root claim, overlay resources
in the RGD, status fields the preview and data plane resolve through).

No app-studio changes needed — it reads development.components live
from the catalog, so simple-webapp appears in the portal picker and
the assistant's selectable set automatically.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 10, 2026 11:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR upgrades the infrastructure provider’s simple-webapp template into a development-capable, publicly exposed single-container web app template (paralleling the existing application template), updates catalog guidance, generalizes the instance controller to handle multiple exposed instance kinds, and adds a test to pin the dev-mode contract App Studio relies on.

Changes:

  • Rework simple-webapp to v0.2.0 with Gateway API HTTPRoute exposure, spec.development + spec.dataPlane, updated schema validations, and richer catalog/portal metadata.
  • Generalize the instance controller to reconcile a set of “exposed instance kinds” (Application + SimpleWebApp) with different treatment (OIDC vs exposure-only).
  • Add seed-template test coverage asserting simple-webapp is development-capable and that the synthesized dev overlay/status contract is present.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
providers/infrastructure/install/templates/simple-webapp.yaml Reworks template to be dev-capable and publicly exposed; updates schema, portal view, agent guidance, and RGD resources/status.
providers/infrastructure/install/templates/redis-cache.yaml Adds sampleValues and agent usage/outputs guidance for MCP/LLM operational discoverability.
providers/infrastructure/install/templates/application.yaml Updates agent guidance to steer frontend-only use cases to simple-webapp.
providers/infrastructure/docs/template-conventions.md Updates a conventions example to reflect the new simple-webapp schema defaults.
providers/infrastructure/controller/application/controller.go Generalizes reconciliation across multiple exposed instance kinds; adds exposure-only treatment for SimpleWebApp.
providers/infrastructure/backend/kro/seedtemplates_test.go Adds a test pinning simple-webapp dev-mode overlay + status fields and required synthesized resources.


// Deletion: clean up the cross-cluster bridged Secret, then drop the
// finalizer so the instance can be removed.
if !app.GetDeletionTimestamp().IsZero() {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

metav1.Time.IsZero() has a pointer receiver with an explicit nil check ("IsZero returns true if the value is nil or time is zero"), so a nil deletion timestamp cannot panic here — the same unguarded idiom is used a few lines below on the Application path (and was there before this PR). The redundant != nil && that likely prompted this was simplified to match.

simple-webapp now ships sampleValues, so the standalone-kro e2e uses
them instead of its minimal spec — but no instance controller runs in
that harness, so nothing stamped spec.expose.fqdn and the HTTPRoute
hostname could never render (kro never created the child; the test
timed out). Give simple-webapp the same e2ePlatformStamped treatment
the application template already has, and drop its now-dead
e2eMinimalSpecs entry.

Also simplify the exposure-only deletion check to the same nil-safe
metav1.Time.IsZero() idiom the Application path uses (review feedback:
the extra nil guard was redundant, not protective).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 10, 2026 12:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment on lines 82 to 86
// e2eMinimalSpecs supplies a valid instance spec for templates that ship no
// sampleValues (those that do — application, database — use them directly).
var e2eMinimalSpecs = map[string]map[string]any{
"redis-cache": {"name": "e2e-redis"},
"simple-webapp": {"name": "e2e-web"},
"redis-cache": {"name": "e2e-redis"},
}
| Kind | How to express it | Example |
|---|---|---|
| **Per-instance, configurable** (image, version, size, replicas) | `spec.schema` field **with a `default`**; the resource references `${schema.spec.<field>}` | `simple-webapp.spec.image` (`default: "nginx:latest"`); `postgres-database.spec.version` |
| **Per-instance, configurable** (image, version, size, replicas) | `spec.schema` field **with a `default`**; the resource references `${schema.spec.<field>}` | `simple-webapp.spec.port` (`default: 8080`); `postgres-database.spec.version` |
@mjudeikis mjudeikis merged commit a4c8370 into main Jul 10, 2026
25 of 26 checks passed
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.

2 participants