feat(previews): preview environments UI + fix latent insert bugs

- Service detail gains a Previews section: list, create (branch/PR/TTL),
  promote-to-production, delete — all confirmed actions. Verified e2e
  create→list→promote→delete.
- fix: preview create scanned services.type which real services leave NULL
  (writes go to service_type); every create 404'd. Now COALESCE(type,
  service_type, '') matching the rest of the codebase.
- fix: deployments.version is NOT NULL but three inserts omitted it —
  handleCreateDeployment, rollback, and preview promote all failed on any
  fresh-install schema. All three now write a version.
- Roadmap notes preview envs are bookkeeping-only; real branch deploy is
  tracked separately.

Authored By: TDvorak <[email protected]>
This commit is contained in:
Tomas Dvorak committed 2026-09-17 18:00:18 +02:00
1 parent 07ac54aa05
commit 8ecc8dcea5
5 files changed
+228 -17

No files matched your search

@@ -201,7 +201,7 @@ func handleCreatePreviewEnvironment(c *gin.Context) {
// Check if service exists and belongs to the project
var service Service
err = db.(*database.DB).QueryRow(
"SELECT id, name, type FROM services WHERE id = $1 AND project_id = $2",
"SELECT id, name, COALESCE(type, service_type, '') FROM services WHERE id = $1 AND project_id = $2",
req.ServiceID, req.ProjectID,
).Scan(&service.ID, &service.Name, &service.Type)
@@ -586,10 +586,11 @@ func handlePromotePreviewEnvironment(c *gin.Context) {
}
deploymentID := uuid.New()
promotionVersion := fmt.Sprintf("promote-%s-%d", strings.ReplaceAll(env.BranchName, "/", "-"), time.Now().Unix())
_, err = db.(*database.DB).Exec(
`INSERT INTO deployments (id, service_id, status, created_at, updated_at)
VALUES ($1, $2, $3, NOW(), NOW())`,
deploymentID, env.ServiceID, "pending",
`INSERT INTO deployments (id, service_id, version, status, created_at, updated_at)
VALUES ($1, $2, $3, $4, NOW(), NOW())`,
deploymentID, env.ServiceID, promotionVersion, "pending",
)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create promotion deployment"})