feat(templates): one-click demo deploy for activation (no Git account)#157
Conversation
Rollback previously reused the target deployment's stored Docker image. That path is fragile: - The nightly cleanup prunes dangling images after ~7 days, so rolling back to anything older fails with "image no longer exists locally". - It sets health_check_path=None, routing traffic before the container is confirmed listening. - It can't reconstruct static deployments (the prior image lacks a server runtime). For git-sourced projects that carry a commit/branch, rollback now re-runs the full build pipeline at the target deployment's commit via trigger_pipeline, instead of reusing the image. This always works (no dependency on a surviving image), goes through the same build + health-check pipeline as a normal deploy, and rebuilds static bundles correctly. Non-git projects (docker_image / static_files / manual without a git ref) have no source to rebuild and keep the existing image-reuse path unchanged. Mechanism: GitPushEventJob gains an optional rollback_from_deployment_id (#[serde(default)] for back-compat). When set, process_git_push_event marks the created deployment is_rollback / rolled_back_from_id and tags context_vars with trigger=rollback. trigger_pipeline delegates to a new trigger_pipeline_inner that carries the marker; the public signature is unchanged. Tests: new test_rollback_rebuilds_from_source_for_git_projects asserts a git deployment with a commit takes the rebuild path (no synchronous image-reuse row). Existing test_rollback_to_deployment (no git ref) still exercises and passes the image-reuse path.
… only when gone The git-rollback path rebuilt from source unconditionally, even when the target deployment's image was still in the local Docker cache. Reusing a present image is near-instant and byte-identical to what we're rolling back to, so gate the rebuild on image availability: reuse when the image exists, fall back to rebuild-from-source only when it's pruned or the preset is static (no runnable image). Non-git projects are unchanged. Reworks the rollback tests to cover both branches (image present -> reuse, image missing -> rebuild) and corrects the CHANGELOG wording.
…urce # Conflicts: # CHANGELOG.md
Add an "observability-starter" template and a one-click deploy path so a brand-new user can deploy a fully-instrumented demo app (analytics, error tracking, tracing, Postgres) without first connecting a Git provider or building a project of their own. Backend (temps-projects): - POST /projects/from-template now accepts an optional git_provider_connection_id. When omitted, the project deploys directly from the template's PUBLIC source repo (is_public_repo + git_url + the template subfolder as the build directory) instead of forking it. Owner/repo labels are derived from the public URL so the deploy pipeline plans the clone and auto-queues the first deploy. Fork mode is unchanged and now validates that repository_name is present. - Emit ProjectCreated + new ProjectCreatedFromTemplate telemetry events (with non-identifying template_slug / forked / service_count) on success. Frontend (web): - TemplateConfigurator no longer dead-ends at "No Git Provider Connected". With no connection it shows a "deploy from public source" affordance and deploys in public-repo mode; fork-only fields (repo name/owner/visibility) are hidden. git_provider_connection_id is now optional in the form/SDK. - Auto-select an existing service that satisfies a template requirement (e.g. an existing Postgres) so returning users get it attached with zero extra clicks; new users create one via the existing Add Service flow. - FirstProjectOnboarding empty state gains a "Try the demo app" banner that one-click deploys the observability-starter template (only shown when there are zero projects, by construction). Template registered in temps-core/templates.yaml pointing at gotempsh/temps-examples (subfolder examples/observability-starter), featured, postgres service. Tests added for the bundled templates and the public-URL owner/repo parser; telemetry count assertion updated.
|
Adds an image-based deploy path for templates so the one-click "Try the demo app" activation flow can pull and run a prebuilt image in seconds instead of building from source (which is multi-minute and BuildKit-heavy). Build-from- source remains the fallback for templates without an image. - temps-core: ProjectTemplate gains optional `image` / `exposed_port` / `health_check_path`; new `Job::DeployImageRequested` (project-scoped, mirrors GitPushEvent). templates.yaml: observability-starter now carries `image: ghcr.io/gotempsh/observability-starter:latest` + port 3000, keeping its `git:` block as the build fallback. - temps-projects: create_project_from_template gains an image branch — when the template has an `image`, it creates a docker_image project (exposed_port from the template) and fires Job::DeployImageRequested; otherwise the existing fork / public-repo build paths run. ProjectCreatedFromTemplate telemetry now carries `deploy_mode` (image|fork|public_repo). TemplateResponse exposes the three new fields. - temps-deployments: job_processor consumes Job::DeployImageRequested — resolves the project's production environment(s) and creates a source_type=docker_image deployment (external_image_ref in metadata) so the workflow planner skips download_repo+build_image and plans a pull+run pipeline. Mirrors the deploy_from_image handler. - web: TemplateConfigurator shows a "deploys instantly from a prebuilt image" note and hides the Git/source section for image templates; SDK TemplateResponse type extended (hand-scoped to avoid regen drift). Image-mode wins over a Git connection (fastest activation). The prebuilt image is published to GHCR by CI in gotempsh/temps-examples.
|
Added image-based template deploy (commit What: templates can now carry a prebuilt
Verification: 3 crates compile, 179 + 387 tests pass, clippy + frontend tsc/lint clean. CI image publish verified green. The live Temps-orchestrated image deploy will be exercised in a separate env (local Docker registry pulls are blocked by a Docker Desktop proxy here). |
The DeployImageRequested consumer created the deployment + jobs and set the deployment Running, but never triggered the workflow executor, so the pull_external_image / deploy_container jobs sat pending forever. Call workflow_executor.execute_deployment_workflow after planning (mirrors the git-push path), and mark the deployment Failed if execution errors. Verified end-to-end: one-click image-template deploy now pulls ghcr.io/gotempsh/observability-starter and runs the container in ~8s (no build), app serves 200 with all pillars.
The Redeploy / New Deployment action routed every project through the git
pipeline (trigger-pipeline), which rejects docker_image projects (no repo
info) and rendered "Deploy from: N/A, Type: Commit". Image-template projects
were therefore impossible to redeploy from the UI.
RedeploymentModal now shows an image-deploy view (image ref + environment, no
branch/commit/tag) when project.source_type === 'docker_image'. ProjectDeployments
and DeploymentDetails resolve the prebuilt image ref from the (most recent /
selected) deployment's metadata.externalImageRef and route confirmation through
deployFromImage instead of triggerProjectPipeline. Backend already supported
this (POST /projects/{id}/environments/{env}/deploy/image) — verified a
redeploy completes in ~10s re-pulling the image.
The DSN builder stripped the port (`.replace(":8080", "")`) and hard-coded
`https://`, so a local instance configured at http://host.docker.internal:8080
produced `https://<key>@host.docker.internal/4` — wrong scheme AND no port, so
the Sentry SDK sent events to :443 and they never reached the ingest. (The OTEL
endpoint was fine because it uses the full base_url.)
Replace all three DSN-build sites (create / existing / rotate) with a shared
build_dsn() that keeps {scheme}://{key}@{host[:port]}/{project_id} intact and
drops only a trailing path/slash. Verified: a redeploy now injects
SENTRY_DSN=http://<key>@host.docker.internal:8080/4. Unit test added.
The earlier redeploy fix only wired imageRef into the empty-state modal instance; the primary RedeploymentModal (rendered when deployments exist) still lacked it, so its image showed 'N/A' and the Deploy button stayed disabled — blocking redeploy from the UI. Wire imageRef + redeployImage.isPending into the second instance as well. Verified in-browser: image now shows ghcr.io/gotempsh/observability-starter:latest and Deploy is enabled.
Resolves jobs.rs conflict: GitPushEventJob gains rollback_from_deployment_id (from #155) alongside the new DeployImageRequestedJob (this branch). Both features coexist; workspace compiles and temps-core tests pass (179). Also applies cargo fmt to a pre-existing long assert_eq! in dsn_service.rs.
What
A one-click deploy path so a brand-new user can deploy a fully-instrumented demo app — analytics, error tracking, distributed tracing, and a Postgres database — without first connecting a Git provider or building a project of their own. This is the activation unblock: see Temps in action in one click.
Pairs with the new
observability-starterexample ingotempsh/temps-examples(already onmain).Changes
Backend (
temps-projects,temps-core)POST /projects/from-templatenow accepts an optionalgit_provider_connection_id.repository_nameis present).is_public_repo+git_url+ the template subfolder as the build directory). Owner/repo labels are derived from the public URL so the deploy pipeline plans the clone and auto-queues the first deploy.TelemetryEventKind::ProjectCreatedFromTemplate(non-identifyingtemplate_slug/forked/service_count), emitted alongsideProjectCreated.Frontend (
web)TemplateConfiguratorno longer dead-ends at "No Git Provider Connected" — with no connection it shows a "deploy from public source" affordance and deploys in public-repo mode; fork-only fields (repo name/owner/visibility) are hidden.FirstProjectOnboardingempty state gains a "Try the demo app" banner that one-click deploys the template (only shown when there are zero projects, by construction).Template
observability-starterregistered intemps-core/templates.yaml(featured,postgresservice, →gotempsh/temps-examplessubfolderexamples/observability-starter).Tests / verification
cargo test -p temps-core -p temps-projects→ 179 + 46 pass (new tests for bundled templates + public-URL owner/repo parser; telemetry count updated). Clippy clean.tsc+eslintclean.201, project created with correct subfolder / public-repo / derived-owner fields, environment + deployment auto-queued. Fork-mode validation returns400without a repo name.Notes
CreateProjectFromTemplateRequestto avoid unrelated regen drift on this branch.