feat(apps): stepped creation wizard, branch previews, and app-creation fixes
This session (frontend focus):
- Rebuild /apps/new as a 4-step wizard (Basics → Configure → Trigger → Review):
WizardRail, SourceKindPicker card grid, AppManifest review, per-step validation,
ConfirmDialog-based unsaved-changes guard.
- Extract lib/workload/sourceForms.ts (single source of truth for source_config)
+ {Image,Compose,Static,Dockerfile}SourceForm + StaticDiscoveryWizard; fold the
/apps/[id] edit form onto the same components (removes the duplication). Add
vitest + sourceForms unit tests.
- Branch preview environments UI: /chain is_preview/preview_branch + a Preview
environments panel on /apps/[id] (per-branch URLs, ConfirmDialog teardown, armed
state); RegistryImagePicker on the registry trigger and the image source.
- Fixes: image-inspect 404 -> admin-gated POST /api/discovery/image/inspect;
conflict-panel blur flicker; friendly localized discovery errors; CPU/Memory
label hints; dashboard + /apps "Total workloads" count only source_kind workloads
(drop stale trigger_kind gate); NPM cert/access-list name cache; EntityPicker
empty-list guard.
- Update CLAUDE.md frontend conventions + add a Build & Test section.
Also captures pre-existing in-progress platform work (not from this session):
workload notifications, Prometheus metrics export, store lockfile, health probes,
backup hardening, and related store/webhook/scheduler changes.
This commit is contained in:
@@ -444,22 +444,12 @@ func updateStatus(deps plugin.Deps, w plugin.Workload, status, commitSHA, errMsg
|
||||
}
|
||||
|
||||
// dispatchSiteNotification fires a site_sync_success or
|
||||
// site_sync_failure event to the configured outbound webhook.
|
||||
// Resolution: per-workload URL+secret first, then fall through to
|
||||
// settings.notification_url/secret. Always best-effort.
|
||||
// site_sync_failure event for the workload via the shared multi-route
|
||||
// dispatcher in plugin.DispatchNotificationForWorkload. Resolution
|
||||
// order (workload_notifications → legacy single URL → settings global)
|
||||
// is identical to the dockerfile plugin's path so receivers see
|
||||
// consistent fan-out behaviour across source kinds.
|
||||
func dispatchSiteNotification(deps plugin.Deps, w plugin.Workload, domain, status, errMsg string) {
|
||||
if deps.Notifier == nil {
|
||||
return
|
||||
}
|
||||
settings, err := deps.Store.GetSettings()
|
||||
if err != nil {
|
||||
slog.Warn("static site: notify settings lookup failed", "site", w.ID, "error", err)
|
||||
return
|
||||
}
|
||||
url, secret, tier := resolveSiteTarget(w, settings)
|
||||
if url == "" {
|
||||
return
|
||||
}
|
||||
eventType := "site_sync_success"
|
||||
if status == "failed" {
|
||||
eventType = "site_sync_failure"
|
||||
@@ -468,7 +458,7 @@ func dispatchSiteNotification(deps plugin.Deps, w plugin.Workload, domain, statu
|
||||
if domain != "" {
|
||||
siteURL = "https://" + domain
|
||||
}
|
||||
deps.Notifier.SendSigned(url, secret, tier, notify.Event{
|
||||
plugin.DispatchNotificationForWorkload(deps, w, notify.Event{
|
||||
Type: eventType,
|
||||
Project: w.Name,
|
||||
URL: siteURL,
|
||||
@@ -476,16 +466,6 @@ func dispatchSiteNotification(deps plugin.Deps, w plugin.Workload, domain, statu
|
||||
})
|
||||
}
|
||||
|
||||
// resolveSiteTarget mirrors the legacy resolveSiteTarget helper but
|
||||
// reads notification config off the workload row (where it now lives
|
||||
// post-refactor) rather than the static_sites row.
|
||||
func resolveSiteTarget(w plugin.Workload, settings store.Settings) (string, string, notify.Tier) {
|
||||
if w.NotificationURL != "" {
|
||||
return w.NotificationURL, w.NotificationSecret, notify.TierSite
|
||||
}
|
||||
return settings.NotificationURL, settings.NotificationSecret, notify.TierSettings
|
||||
}
|
||||
|
||||
// publishEvent emits a static_site_status event on the bus AND
|
||||
// persists an event_log row so the dashboard's audit trail picks it
|
||||
// up. Message format ("Static site \"%s\": %s") is preserved verbatim
|
||||
|
||||
Reference in New Issue
Block a user